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

About these ads

7 thoughts on “A Look At Tasks In The System.Threading.Tasks VS2010 Namespace

  1. Hi Sacha,

    In my project I have to refresh the objects state updating data from web service with preset refresh rate varying from 100 milliseconds to 10 seconds.

    The system should monitor this way from 5 to 50 objects.

    Is the Threading.Tasks good alternative for me because I think I cannot reuse Task/s, so maybe for such purpose is better to use CCR where I can reuse Job/s.

    What is your opinion? Or maybe there are some other libraries I could use without developing my own thread pooling system.

    Best regards
    Stefan

    • sacha says:

      Yeah I think the Tasks namespace would probably be a good thing to use there, just kick of a Task every n-time. Should be ok I think

  2. Clint says:

    Hi Sacha,

    Thanks for all your time spent for the community! Much appreciated!

    In your code project sample have you managed to resolve the issue with the ‘VERY LONG TASK’ blocking the Wpf UI thread. I’ve also looked at this and can’t understand why this is so as I can quite clearly see there is another thread created using the debugger threads view.

    I would really like to use the Task class in WPF but not if it doesn’t work as advertised!

    BTW I needed to update a few things for VS2010B2 using .NET 4.0.21006 B2Rel!?

    Clint

    • sacha says:

      Yeah to solve that issue you not Wait() on the Task but rather use a Continuation and that is when you know its finished.

      These days I still tend to use BackgroundWorker and the stuff from my Cinch WPF MVVM library, oh and this new threading component works wonders for us :

      http://sachabarber.net/?p=642

      Hope it helps you

  3. Rauf says:

    Hi, this is great work. I am looking to get all the tasks executing within a program. Any idea, how can I retrieve this information using System.Threading.Tasks namespace.

    Thanks in anticipation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s