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: }
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: }
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:


























Stefan said
am December 3 2009 @ 2:19 pm
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 said
am December 3 2009 @ 2:33 pm
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
Clint said
am January 18 2010 @ 5:26 am
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 said
am January 18 2010 @ 8:37 am
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