Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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 the
Task.RunEx
TaskEx.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);
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);
button.Content = "Start";
cts.Cancel();
–
–
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:
Potential pitfalls to avoid when passing around async lambdas
Task.Run vs Task.Factory.StartNew
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.
–
–
–
–
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.
Task.Run spawns a new thread in most scenarios as I understand it.
It's important to note that simply because you mark a method as async, and use awaiters, this does NOT (necessarily) mean that new threads are being created, completions are scheduled on the SAME thread of execution that they were called from in many cases.
The trick here has to do with the SchedulingContext. If it's set for a multithreaded apartment, then you're going to delegate completions to viable threads on the threadpool. If you're in a singlethreaded apartment as all WPF and WinForms UI code is, then it will return to the calling thread for completion allowing work to be done directly on the UI without visible thread marshalling in the code.
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.