Category Archives: Beginners Guide To Threading

Task Parallel Library 5 of n

I have just published part 5 in my series of TPL articles.. This time I talks about This time I talk about BlockingCollection<T> and creating pipelines, you can read the article here : http://www.codeproject.com/KB/cs/Tasks5.aspx

Advertisements

Task Parallel Library 1 of n

I have just started work on what will be a 6 part series of articles on an in depth look into using the .NET 4 Task Parallel Library (TPL).

I have just published the 1st part in this series of article which is available using this link:

http://www.codeproject.com/KB/cs/TPL1.aspx

  • This article covers the following topics:
  • Comparing Threads and Tasks
  • Starting Tasks
  • Handling Exceptions With Tasks
  • Cancelling Tasks
  • UI Synchronization Using Tasks

I hope it has something there for you, and i hope you read the rest of the articles when I get them up.

A Look At Tasks In The System.Threading.Tasks VS2010 Namespace

I had a bit of time today to look at the System.Threading.Tasks VS2010 Namespace, and I started throwing a bit of code together and wrote an article about which you can read over at

http://www.codeproject.com/KB/threads/TPLTasks.aspx

But if you just want a quick overview, what the Tasks in the System.Threading.Tasks VS2010 Namespace are all about (from what I read anyhow), is a replacement for queuing work items up using the currently available ThreadPool. The issue with the current ThreadPool is that

  • Work items can’t return a value
  • Can not cancel tasks
  • No waiting on work items
  • Composing a group of items in a structured way
  • Handling exceptions thrown concurrently or any other richer construct built on top of it

 

So Tasks are there to help out in this area. Let’s have a quick look at how to do some common things such as

 

Run A Task That Returns A Value

   1:     /// <summary>
   2:          /// This handler shows you to use a Task that
   3:          /// doesn't use any state inside the Task
   4:          /// 
   5:          /// This Task blocks the calling thread until the 
   6:          /// Task completes
   7:          /// </summary>
   8:          private void TaskFactWithReturnValue_Click(object sender, 
   9:              RoutedEventArgs e)
  10:          {
  11:              Func<ObservableCollection<String>> obtainTaskResults 
  12:                  = TaskWithResults;
  13:              Task<ObservableCollection<String>> task =
  14:                  Task.Factory.StartNew<ObservableCollection<String>>
  15:                  (obtainTaskResults,
  16:                  TaskCreationOptions.DetachedFromParent);
  17:              items.Clear();
  18:              task.Wait(); //Blocks while waiting for Task to complete
  19:              items = task.Result;
  20:              lstItems.ItemsSource = items;
  21:              MessageBox.Show("TaskFactWithReturnValue DONE");
  22:          }
  23:   
  24:          /// <summary>
  25:          /// Runs the Tasks Func delegate, which returns 
  26:          /// a list of ObservableCollection String
  27:          /// </summary>
  28:          private ObservableCollection<String> TaskWithResults()
  29:          {
  30:              ObservableCollection<String> results = 
  31:                  new ObservableCollection<string>();
  32:              for (int i = 0; i < 10; i++)
  33:              {
  34:                  results.Add(String.Format(
  35:                      "TaskFactWithReturnValue Item {0}", i));
  36:              }
  37:              return results;
  38:   
  39:          }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And we can even chain tasks together using a technique called Continuations, here is an example of that:

   1:         /// <summary>
   2:          /// This handler shows you to use a Task that will 
   3:          /// use 2 chained Tasks the first Task accepts some
   4:          /// State, and the 2nd Task in the chain doesn't
   5:          /// ONLY when both Tasks have completed is the work 
   6:          /// considered done
   7:          /// 
   8:          /// This Task blocks the calling thread until the 
   9:          /// 2 chained Task complete
  10:          /// </summary>
  11:          private void TaskContinue_Click(object sender, 
  12:              RoutedEventArgs e)
  13:          {
  14:              //SYNTAX EXAMPLE 1
  15:              #region SYNTAX EXAMPLE 1
  16:              Func<Object, ObservableCollection<String>> 
  17:                  obtainTaskResultsFunc = 
  18:                  TaskWithResultsWithState;
  19:              Task<ObservableCollection<String>> task =
  20:                  Task.Factory.StartNew(obtainTaskResultsFunc, 
  21:                  new ObjectState<Int32>
  22:                  {
  23:                      CurrentTask = "TaskState",
  24:                      Value = 2
  25:                  });
  26:   
  27:              Func<Task, ObservableCollection<String>> 
  28:                  contineResultsFunc = ContinueResults;
  29:              Task<ObservableCollection<String>>
  30:                  continuationTask =
  31:                  task.ContinueWith<ObservableCollection<String>>
  32:                  (contineResultsFunc,
  33:                  TaskContinuationOptions.OnlyOnRanToCompletion);
  34:   
  35:              continuationTask.Wait();
  36:              items.Clear();
  37:              items = continuationTask.Result;
  38:              #endregion
  39:   
  40:              //SYNTAX EXAMPLE 2
  41:              #region SYNTAX EXAMPLE 2
  42:              //Task<ObservableCollection<String>> taskAll =
  43:              //    Task.Factory.StartNew((o) =>
  44:              //        {
  45:              //            return TaskWithResultsWithState(o);
  46:              //        }, new ObjectState<Int32>
  47:              //            {
  48:              //                CurrentTask = "TaskState",
  49:              //                Value = 2
  50:              //            }).ContinueWith<ObservableCollection
  51:              //              <String>>((previousTask) =>
  52:              //                {
  53:              //                    return ContinueResults(
  54:              //                      previousTask);
  55:              //                },TaskContinuationOptions.
  56:              //                  OnlyOnRanToCompletion);
  57:   
  58:   
  59:              //taskAll.Wait(); 
  60:              //items.Clear();
  61:              //items = taskAll.Result;
  62:              #endregion
  63:   
  64:   
  65:              lstItems.ItemsSource = items;
  66:              MessageBox.Show("TaskContinue DONE");
  67:          }
  68:   
  69:   
  70:   
  71:          /// <summary>
  72:          /// Runs the Tasks Func delegate, which returns a list
  73:          /// of ObservableCollection String
  74:          /// </summary>
  75:          private ObservableCollection<String> 
  76:              TaskWithResultsWithState(Object o)
  77:          {
  78:              var state = o as ObjectState<Int32>;
  79:              ObservableCollection<String> results = 
  80:                  new ObservableCollection<string>();
  81:              for (int i = 0; i < state.Value; i++)
  82:              {
  83:                  results.Add(String.Format("{0} Item {1}", 
  84:                      state.CurrentTask, i));
  85:              }
  86:              return results;
  87:   
  88:          }
  89:   
  90:          /// <summary>
  91:          /// Runs the Contination Tasks Func delegate, 
  92:          /// which returns a list
  93:          /// of ObservableCollection String
  94:          /// </summary>
  95:          private ObservableCollection<String> 
  96:              ContinueResults(Task originalTask)
  97:          {
  98:   
  99:              Task<ObservableCollection<String>> taskOriginal 
 100:                  = originalTask as Task<ObservableCollection<String>>;
 101:   
 102:              ObservableCollection<String> results = 
 103:                  new ObservableCollection<string>();
 104:   
 105:              ObservableCollection<String> orginalResults =
 106:                  taskOriginal.Result as 
 107:                  ObservableCollection<String>;
 108:   
 109:              foreach (var item in orginalResults)
 110:                  results.Add(item);
 111:   
 112:              for (int i = 0; i < 10; i++)
 113:                  results.Add(
 114:                      String.Format(
 115:                      "ContinueResults Item {0}", i));
 116:   
 117:              return results;
 118:          }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

As I say I go through all this a lot more in my article, which is available at the following Url should you want to know more:

 

http://www.codeproject.com/KB/threads/TPLTasks.aspx

ThreadSafeObservableCollection

As part of an ongoing article I am just about to finish, I needed a thread safe ObservableCollection<T>. Now the native .NET framework doesn’t have one of those, but luckily it supplies you with the right job to create one using some of the Threading APIs.

Here is what I came up with.

 

   1:  /// <summary>
   2:  /// Provides a threadsafe ObservableCollection of T
   3:  /// </summary>
   4:  public class ThreadSafeObservableCollection<T>
   5:      : ObservableCollection<T>
   6:  {
   7:      #region Data
   8:      private Dispatcher _dispatcher;
   9:      private ReaderWriterLockSlim _lock;
  10:      #endregion
  11:  
  12:      #region Ctor
  13:      public ThreadSafeObservableCollection()
  14:      {
  15:          _dispatcher = Dispatcher.CurrentDispatcher;
  16:          _lock = new ReaderWriterLockSlim();
  17:      }
  18:      #endregion
  19:  
  20:  
  21:      #region Overrides
  22:  
  23:      /// <summary>
  24:      /// Clear all items
  25:      /// </summary>
  26:      protected override void ClearItems()
  27:      {
  28:          _dispatcher.InvokeIfRequired(() =>
  29:              {
  30:                  _lock.EnterWriteLock();
  31:                  try
  32:                  {
  33:                      base.ClearItems();
  34:                  }
  35:                  finally
  36:                  {
  37:                      _lock.ExitWriteLock();
  38:                  }
  39:              }, DispatcherPriority.DataBind);
  40:      }
  41:  
  42:      /// <summary>
  43:      /// Inserts an item
  44:      /// </summary>
  45:      protected override void InsertItem(int index, T item)
  46:      {
  47:          _dispatcher.InvokeIfRequired(() =>
  48:          {
  49:              if (index > this.Count)
  50:                  return;
  51:  
  52:              _lock.EnterWriteLock();
  53:              try
  54:              {
  55:                  base.InsertItem(index, item);
  56:              }
  57:              finally
  58:              {
  59:                  _lock.ExitWriteLock();
  60:              }
  61:          }, DispatcherPriority.DataBind);
  62:  
  63:      }
  64:  
  65:      /// <summary>
  66:      /// Moves an item
  67:      /// </summary>
  68:      protected override void MoveItem(int oldIndex, int newIndex)
  69:      {
  70:          _dispatcher.InvokeIfRequired(() =>
  71:          {
  72:              _lock.EnterReadLock();
  73:              Int32 itemCount = this.Count;
  74:              _lock.ExitReadLock();
  75:  
  76:              if (oldIndex >= itemCount |
  77:                  newIndex >= itemCount |
  78:                  oldIndex == newIndex)
  79:                  return;
  80:  
  81:              _lock.EnterWriteLock();
  82:              try
  83:              {
  84:                  base.MoveItem(oldIndex, newIndex);
  85:              }
  86:              finally
  87:              {
  88:                  _lock.ExitWriteLock();
  89:              }
  90:          }, DispatcherPriority.DataBind);
  91:  
  92:  
  93:  
  94:      }
  95:  
  96:      /// <summary>
  97:      /// Removes an item
  98:      /// </summary>
  99:      protected override void RemoveItem(int index)
 100:      {
 101:  
 102:          _dispatcher.InvokeIfRequired(() =>
 103:          {
 104:              if (index >= this.Count)
 105:                  return;
 106:  
 107:              _lock.EnterWriteLock();
 108:              try
 109:              {
 110:                  base.RemoveItem(index);
 111:              }
 112:              finally
 113:              {
 114:                  _lock.ExitWriteLock();
 115:              }
 116:          }, DispatcherPriority.DataBind);
 117:      }
 118:  
 119:      /// <summary>
 120:      /// Sets an item
 121:      /// </summary>
 122:      protected override void SetItem(int index, T item)
 123:      {
 124:          _dispatcher.InvokeIfRequired(() =>
 125:          {
 126:              _lock.EnterWriteLock();
 127:              try
 128:              {
 129:                  base.SetItem(index, item);
 130:              }
 131:              finally
 132:              {
 133:                  _lock.ExitWriteLock();
 134:              }
 135:          }, DispatcherPriority.DataBind);
 136:      }
 137:      #endregion
 138:  
 139:      #region Public Methods
 140:      /// <summary>
 141:      /// Return as a cloned copy of this Collection
 142:      /// </summary>
 143:      public T[] ToSyncArray()
 144:      {
 145:          _lock.EnterReadLock();
 146:          try
 147:          {
 148:              T[] _sync = new T[this.Count];
 149:              this.CopyTo(_sync, 0);
 150:              return _sync;
 151:          }
 152:          finally
 153:          {
 154:              _lock.ExitReadLock();
 155:          }
 156:      }
 157:      #endregion
 158:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

It relies on this small extension method

 

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }

   1:  /// <summary>
   2:  /// WPF Threading extension methods
   3:  /// </summary>
   4:  public static class WPFControlThreadingExtensions
   5:  {
   6:      #region Public Methods
   7:      /// <summary>
   8:      /// A simple WPF threading extension method, to invoke a delegate
   9:      /// on the correct thread if it is not currently on the correct thread
  10:      /// Which can be used with DispatcherObject types
  11:      /// </summary>
  12:      /// <param name="disp">The Dispatcher object on which to do the Invoke</param>
  13:      /// <param name="dotIt">The delegate to run</param>
  14:      /// <param name="priority">The DispatcherPriority</param>
  15:      public static void InvokeIfRequired(this Dispatcher disp,
  16:          Action dotIt, DispatcherPriority priority)
  17:      {
  18:          if (disp.Thread != Thread.CurrentThread)
  19:          {
  20:              disp.Invoke(priority, dotIt);
  21:          }
  22:          else
  23:              dotIt();
  24:      }
  25:      #endregion
  26:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }Hope it is useful to someone. Enjoy

Useful WPF Threading Extension Method

If you are working with WinForms or WPF you will more than likely run into some long running operation that you would like to run in a new thread. A novice may actually try and create a new Thread, which is ok, but that means you are responsible for the entire lifecycle of your new thread. Which gets tricky.

A better approach would be to use the ThreadPool or use a BackgroundWorker component which uses the ThreadPool beneath the surface.

However, even using these approaches the cardinal rule is that the control is owned by 1 thread, the thread that created the controls. That is typically the UI thread. So when you try and update the controls from a background thread you will run into problems.

This code demonstrates the problem with cross thread calls :

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Windows;
   6:  using System.Windows.Controls;
   7:  using System.Windows.Data;
   8:  using System.Windows.Documents;
   9:  using System.Windows.Input;
  10:  using System.Windows.Media;
  11:  using System.Windows.Media.Imaging;
  12:  using System.Windows.Navigation;
  13:  using System.Windows.Shapes;
  14:  using System.ComponentModel;
  15:  using System.Windows.Threading;
  16:  
  17:  namespace BackgroundThread
  18:  {
  19:  
  20:  
  21:      public partial class Window1 : Window
  22:      {
  23:          private Int32 currentCount = 0;
  24:          private Int32 maxCount = 500;
  25:          private float factor = 0;
  26:  
  27:          public Window1()
  28:          {
  29:              InitializeComponent();
  30:  
  31:          }
  32:  
  33:          private void btnGo_Click(object sender, RoutedEventArgs e)
  34:          {
  35:              factor = (float)100 / maxCount;
  36:  
  37:              BackgroundWorker bgWorker = new BackgroundWorker();
  38:              bgWorker.WorkerReportsProgress = true;
  39:              bgWorker.WorkerSupportsCancellation = false;
  40:  
  41:              //DoWork
  42:              bgWorker.DoWork += (s2, e2) =>
  43:              {
  44:                  for (currentCount = 0;
  45:                      currentCount < maxCount; currentCount++)
  46:                  {
  47:                      lstItems.Items.Add(
  48:                          String.Format("Count {0}", currentCount));
  49:                  }
  50:              };
  51:  
  52:              //ProgressChanged
  53:              bgWorker.ProgressChanged += (s3, e3) =>
  54:              {
  55:                  pgbar.Value = e3.ProgressPercentage;
  56:              };
  57:  
  58:              bgWorker.RunWorkerAsync();
  59:  
  60:          }
  61:      }
  62:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Which when run will result in the following:

crossThread

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

So how can we fix this, well we could use the Dispatcher.Invoke around the offending items, but perhaps a more elegant solution may be to use a extension method.

   1:  public static class WPFThreadingExtensions
   2:  {
   3:      /// <summary>
   4:      /// Simple helper extension method to marshall to correct
   5:      /// thread if its required
   6:      /// </summary>
   7:      /// <param name="control">The source control</param>
   8:      /// <param name="methodcall">The method to call</param>
   9:      /// <param name="priorityForCall">The thread priority</param>
  10:      public static void InvokeIfRequired(
  11:          this DispatcherObject control,
  12:          Action methodcall,
  13:          DispatcherPriority priorityForCall)
  14:      {
  15:          //see if we need to Invoke call to Dispatcher thread
  16:          if (control.Dispatcher.Thread != Thread.CurrentThread)
  17:              control.Dispatcher.Invoke(priorityForCall, methodcall);
  18:          else
  19:              methodcall();
  20:      }
  21:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Which we can then use in our code as simply as follows :

   1:      factor = (float)100 / maxCount;
   2:  
   3:      BackgroundWorker bgWorker = new BackgroundWorker();
   4:      bgWorker.WorkerReportsProgress = true;
   5:      bgWorker.WorkerSupportsCancellation = false;
   6:  
   7:      //DoWork
   8:      bgWorker.DoWork += (s2, e2) =>
   9:      {
  10:          for (currentCount = 0;
  11:              currentCount < maxCount; currentCount++)
  12:          {
  13:  
  14:              this.InvokeIfRequired(() =>
  15:              {
  16:                  lstItems.Items.Add(
  17:                      String.Format("Count {0}", currentCount));
  18:              },
  19:                  DispatcherPriority.Background);
  20:  
  21:              bgWorker.ReportProgress((int)(factor * (currentCount + 1)));
  22:  
  23:          }
  24:      };
  25:  
  26:      //ProgressChanged
  27:      bgWorker.ProgressChanged += (s3, e3) =>
  28:      {
  29:          this.InvokeIfRequired(() =>
  30:          {
  31:              pgbar.Value = e3.ProgressPercentage;
  32:          },
  33:          DispatcherPriority.Background);
  34:  
  35:  
  36:      };
  37:  
  38:      bgWorker.RunWorkerAsync();
  39:  
  40:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Which when run allows cross threaded calls to be marshaled to the correct Dispatcher object.

better

Hope this helps.
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

NUnit STA Threads & Testing WPF

During the course of the WPF project we are working on at work, we decided to go down the Agile/XP/TDD/Mocks/Continuous Integration route, which means Unit tests, lots of them.

We are using NUnit, which I really like, but we are also using WPF, we are obviously using the latest/greatest patterns AKA MVVM, but from time tom time it is nice to be able to test certain things on WPF controls/windows etc etc.

So I set out to create a small NUnit test like the following:


/* Style Definitions */ table.MsoNormalTable {mso-style-name:”Table Normal”; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:””; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:”Calibri”,”sans-serif”; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:”Times New Roman”; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:”Times New Roman”; mso-bidi-theme-font:minor-bidi;}

diag11.jpg
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Now to me this looked fine, but when I ran this code I got the following horror show.

STAThread

Where NUnit moaned about “The calling thread must be STA”. Oh, that’s to bad. So I had a small think, and then came up with this small idea, just pass the original code to a helper class and have it run that in a Thread using STA threading apartment state. Sounds cool, but did it work. Well yes actually it did, and here is the small helper class.

 

 diag2.jpg


.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }And here is how to use this from a NUnit test.


/* Style Definitions */ table.MsoNormalTable {mso-style-name:”Table Normal”; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:””; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:”Calibri”,”sans-serif”; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:”Times New Roman”; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:”Times New Roman”; mso-bidi-theme-font:minor-bidi;}

diag3.jpg

And just to prove it works, here is a screen shot of the actual test running successfully.

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }STAThreadOK

Here is a link to a small test project that you can see this working with : wpfandnunittest1.zip in case you want to use this in your own projects.

Enjoy

Another threading post is out (Part5)

I have just published another article on threading over at Codeproject. This one deals with threading in UIs.

http://www.codeproject.com/KB/threads/ThreadingDotNet5.aspx

Another Threading Article Is Out (Part2)

As some of you may know I have embarked on a mission to write some articles over at codeproject about threading. Part 2 of this crusade is now available using this link. In this one I talk about how to control Thread state, and also some common threading traps. I hope you enjoy it. It has been critiqued a little, for being a little MSDN like, so Ill try and come up with a different angle on the next article so that there is something different for you to read.

Beginners Guide To Threading In .NET

I have just started a series of articles over at codeproject on threading in .NET.

I don’t know the exact schedule, but it may end up being something like

I hope this will help some folk learn how to use threads. It’s a complex subject, so hopefully these articles will be easy enough for folk to follow.

I certainly hope so anyway.