Multiple Parallel Task.ContinueWith order of execution
Question
This is probably something simple I've missed.
Let's say I do (in loveley VB):
Dim t1 As New Task(Sub() Debug.WriteLine("t1"))
Dim t2 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t2"))
Dim t3 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t3"))
t1.Start()
Notice t1.ContinueWith is used twice. What is the preferred order of execution for these tasks? For me, it's either random or wrong.
Why?
The reason I want to do this...
- Create a task grabbing and returning data
- Followed by a task which "sorts out" the UI on
TaskScheduler.FromCurrentSynchronizationContext()
(UI thread) - Follow the original data grabbing task by converting the data into a long report (takes ages)
- Back on the UI thread, assign that report to a previewing control
- Cleanup (get rid of my prog开发者_Go百科ress animation etc)
This is made more complicated by the fact that step 4 is optional.
In the midst of all this, my tasks are bending backwards to set member properties so the UI and tasks can play nice. Perhaps I should ditch the Task result entirely and just stick to Synclocking my member variables. They are all only assigned once afterall.
Thanks, Tom
The tasks are executed in a LIFO ordering for better memory locality. This can be changed of course if you use a differnt scheduler or if MS decides to "fix" the original one. I do not think that you should rely on this behaviour. Instead you could Unwrap your task to continue working on the previous task when it has completed. Otherwise you are waiting on the wrong thing. More infos can be found here: http://msdn.microsoft.com/en-us/library/ee795275.aspx
If you want to enforce the order between t2 and t3, why don't you just change is so that t3 continues from t2 instead of t1?
Dim t1 As New Task(Sub() Debug.WriteLine("t1"))
Dim t2 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t2"))
Dim t3 As Task = t2.ContinueWith(Sub() Debug.WriteLine("t3"))
t1.Start()
If t2 and t3 were long running they will execute in parallel as you had it written.
There's no need to create a custom task scheduler to change this behavior.
Based on your comment on Ian Mercer's answer I would suggest something like
Task t1 = new Task((_)=>Console.WriteLine("t1"));
Task tn = secondTaskCondition ? t1.ContinueWith((_)=>Console.WriteLine("t2")) : t1;
Task t3 = tn.ContinueWith((_)=>Console.WriteLine("t3"));
t1.Start();
This gives you deterministic execution and still lets you compose your workflow with optional units.
精彩评论