When to use TaskEx.Run vs. TaskEx.RunEx
Solution 1
Use TaskEx.Run
when you want to run synchronous code in a thread pool context.
Use TaskEx.RunEx
when you want to run asynchronous code in a thread pool context.
Stephen Toub has two blog posts related to the difference in behavior:
This is only one of several options you have for creating tasks. If you do not have to use Run
/RunEx
, then you should not. Use simple async
methods, and only use Run
/RunEx
if you need to run something in the background.
Solution 2
The difference between your two DoWork()
methods is that the first one (that uses TaskEx.RunEx()
) is not asynchronous at all. It executes fully synchronously, starts the other task on another thread, and immediately returns a completed Task
. If you await
ed or Wait()
ed on that task, it wouldn't wait until the internal task is completed.
Related videos on Youtube
poco
Updated on June 04, 2022Comments
-
poco almost 2 years
I'm trying to understand when to use
TaskEx.Run
. I have provided two code sample i wrote below that produce the same result. What i fail to see is why i would take theTask.RunExTaskEx.RunEx
approach, I'm sure there is a good reason and was hoping someone could fill me in.async Task DoWork(CancellationToken cancelToken, IProgress<string> progress) { int i = 0; TaskEx.RunEx(async () => { while (!cancelToken.IsCancellationRequested) { progress.Report(i++.ToString()); await TaskEx.Delay(1, cancelToken); } }, cancelToken); } private void Button_Click(object sender, RoutedEventArgs e) { if (button.Content.ToString() == "Start") { button.Content = "Stop"; cts.Dispose(); cts = new CancellationTokenSource(); listBox.Items.Clear(); IProgress<string> progress = new Progress<string>(s => { listBox.Items.Add(s); listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); }); DoWork(cts.Token, progress); } else { button.Content = "Start"; cts.Cancel(); } }
I can achieve the same results like so
async Task DoWork(CancellationToken cancelToken) { int i = 0; while (!cancelToken.IsCancellationRequested) { listBox.Items.Add(i++); listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); await TaskEx.Delay(100, cancelToken); } } private void Button_Click(object sender, RoutedEventArgs e) { if (button.Content.ToString() == "Start") { button.Content = "Stop"; cts.Dispose(); cts = new CancellationTokenSource(); listBox.Items.Clear(); DoWork(cts.Token); } else { button.Content = "Start"; cts.Cancel(); } }
-
Sandra about 12 yearsActually that's not true... RunEx has to do with value returning lambda expressions... not asynchrony. Run handles async lambda's just fine.
-
svick about 12 yearsIn .Net 4.5 DP, there seems to be only
Task.Run()
, noEx
es. -
Phil about 12 yearsTaskEx is in the CTP only. In .Net 4.5 the methods on TaskEx have been integrated into Task.
-
Stephen Cleary about 12 years@svick, @Phil: In .NET 4.5,
TaskEx.Run
becomes an overload ofTask.Run
, andTaskEx.RunEx
also becomes an overload ofTask.Run
. -
Stephen Cleary about 12 years@Firoso:
RunEx
performs an unwrapping of the inner task. If you pass an async lambda toRun
in VS2010, it will work "just fine" -- if you don't care about when it completes. However, if you want the returnedTask
to complete when the async lambda completes, then useTaskEx
. See this blog post or this blog post for more info.