C# spawn new task - c#

Suppose I have this function:
void DoWork()
{
//do long work
}
I want this function to be executed on a different thread.
I'm used to use threads, so one way to execute it on a thread is:
new Thread(DoWork).Start();
I'm trying to learn the new task/await C# feature so I modified the method to
async Task DoWork()
{
await Task.Run(delegate() { /*do stuff*/});
}
Now I can use it this way:
DoWork().Wait(0);
Or I can modify the method again to:
async void DoWork()
{
await Task.Run(delegate() { /*do stuff*/});
}
And now just call:
DoWork();
Which solution should I use ?
I do not need the result of the task nor waiting for it to finish.

The answer is neither. You are creating a trivial asynchronous wrapper around synchronous logic.
Stephen Cleary: using Task.Run for asynchronous wrappers is a code smell
Stephen Toub (Microsoft): Should I expose asynchronous wrappers for synchronous methods? (and no, you shouldn't).
The async part of your DoWork method adds no value. It diminishes the value of your API by making it impossible to execute your potentially complex "do stuff" logic in any way other than fire-and-forget.
The correct approach is to ditch Task.Run and strip your method down to the bare essentials:
void DoWork()
{
// Do long CPU-bound work, synchronously
}
...
// Then, somewhere in the calling code:
Task.Run(() => DoWork()); // Fire and forget unless you await the resulting Task or block on it.
Task.Run is currently the preferred method of scheduling work on the thread pool (as of .NET 4.6.x)

Related

Handling tasks in parallel

Consider an API that returns Tasks with some values.
I want to update the UI based on that values in parallel (when one of the values is ready I want to update it without waiting for the second one assuming the update of each value as its own update method).
public async Task MyFunc()
{
Task<First> firstTask = MyAPI.GetFirstValue();
Task<Second> secondTask = MyAPI.GetSecondValue();
UpdateFirstValueUI(await firstTask)
UpdateSecondValueUI(await secondTask)
}
the code example will wait for the first value, update the UI, wait for the second value and update the UI again.
What is the best practice for that scenario? I was wondering if ContinueWith is best practice because I mostly see it in legacy code (before there was async-await).
edit with a better example:
assuming we have two implementations of that API and the code looks like that
public async Task MyFunc()
{
Task<First> firstTask = null
Task<Second> secondTask = null
if (someCondition)
{
firstTask = MyAPI1.GetFirstValue();
secondTask = MyAPI1.GetSecondValue();
}
else
{
firstTask = MyAPI2.GetFirstValue();
secondTask = MyAPI2.GetSecondValue();
}
UpdateFirstValueUI(await firstTask)
UpdateSecondValueUI(await secondTask)
}
now as you see I don't want call the update methods in two different branches (assuming we split that method for each API after the branching)
so looking for a way to change only the update calls so they could happen in parallel
The ContinueWith is a primitive method that has some rare uses in library code, and should generally be avoided in application code. The main problem with using the ContinueWith in your case is that it's going to execute the continuation on a ThreadPool, which is not what you want, because your intention is to update the UI. And updating the UI from any other thread than the UI thread is a no no. It is possible to solve this¹ problem by configuring the ContinueWith with a suitable TaskScheduler, but it's much simpler to solve it with async/await composition. My suggestion is to add the Run method below in some static class in your project:
public static class UF // Useful Functions
{
public static async Task Run(Func<Task> action) => await action();
}
This method just invokes and awaits the supplied asynchronous delegate. You could use this method to combine your asynchronous API calls with their UI-updating continuations like this:
public async Task MyFunc()
{
Task<First> task1;
Task<Second> task2;
if (someCondition)
{
task1 = MyAPI1.GetFirstValueAsync();
task2 = MyAPI1.GetSecondValueAsync();
}
else
{
task1 = MyAPI2.GetFirstValueAsync();
task2 = MyAPI2.GetSecondValueAsync();
}
Task compositeTask1 = UF.Run(async () => UpdateFirstValueUI(await task1));
Task compositeTask2 = UF.Run(async () => UpdateSecondValueUI(await task2));
await Task.WhenAll(compositeTask1, compositeTask2);
}
This will ensure that the UI will be updated immediately after each asynchronous operation completes.
As a side note, if you have any suspicion that the MyAPI asynchronous methods may contain blocking code, you could offload them to the ThreadPool by using the Task.Run method, like this:
task1 = Task.Run(() => MyAPI1.GetFirstValueAsync());
For a thorough explanation about why this is a good idea, you can check out this answer.
The difference between the built-in Task.Run method and the custom UF.Run method presented above, is that the Task.Run invokes the asynchronous delegate on the ThreadPool, while the UF.Run invokes it on the current thread. If you have any idea about a better name than Run, please suggest. :-)
¹ The ContinueWith comes with a boatload of other problems as well, like wrapping errors in AggregateExceptions, making it easy to swallow exceptions by mistake, making it hard to propagate the IsCanceled status of the antecedent task, making it trivial to leak fire-and-forget tasks, requiring to Unwrap nested Task<Task>s created by async delegates etc.

What should Task.Run(Func<Task>) be used for? [duplicate]

I would like to ask you on your opinion about the correct architecture when to use Task.Run. I am experiencing laggy UI in our WPF .NET 4.5
application (with Caliburn Micro framework).
Basically I am doing (very simplified code snippets):
public class PageViewModel : IHandle<SomeMessage>
{
...
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
// Makes UI very laggy, but still not dead
await this.contentLoader.LoadContentAsync();
HideLoadingAnimation();
}
}
public class ContentLoader
{
public async Task LoadContentAsync()
{
await DoCpuBoundWorkAsync();
await DoIoBoundWorkAsync();
await DoCpuBoundWorkAsync();
// I am not really sure what all I can consider as CPU bound as slowing down the UI
await DoSomeOtherWorkAsync();
}
}
From the articles/videos I read/saw, I know that await async is not necessarily running on a background thread and to start work in the background you need to wrap it with await Task.Run(async () => ... ). Using async await does not block the UI, but still it is running on the UI thread, so it is making it laggy.
Where is the best place to put Task.Run?
Should I just
Wrap the outer call because this is less threading work for .NET
, or should I wrap only CPU-bound methods internally running with Task.Run as this makes it reusable for other places? I am not sure here if starting work on background threads deep in core is a good idea.
Ad (1), the first solution would be like this:
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
await Task.Run(async () => await this.contentLoader.LoadContentAsync());
HideLoadingAnimation();
}
// Other methods do not use Task.Run as everything regardless
// if I/O or CPU bound would now run in the background.
Ad (2), the second solution would be like this:
public async Task DoCpuBoundWorkAsync()
{
await Task.Run(() => {
// Do lot of work here
});
}
public async Task DoSomeOtherWorkAsync(
{
// I am not sure how to handle this methods -
// probably need to test one by one, if it is slowing down UI
}
Note the guidelines for performing work on a UI thread, collected on my blog:
Don't block the UI thread for more than 50ms at a time.
You can schedule ~100 continuations on the UI thread per second; 1000 is too much.
There are two techniques you should use:
1) Use ConfigureAwait(false) when you can.
E.g., await MyAsync().ConfigureAwait(false); instead of await MyAsync();.
ConfigureAwait(false) tells the await that you do not need to resume on the current context (in this case, "on the current context" means "on the UI thread"). However, for the rest of that async method (after the ConfigureAwait), you cannot do anything that assumes you're in the current context (e.g., update UI elements).
For more information, see my MSDN article Best Practices in Asynchronous Programming.
2) Use Task.Run to call CPU-bound methods.
You should use Task.Run, but not within any code you want to be reusable (i.e., library code). So you use Task.Run to call the method, not as part of the implementation of the method.
So purely CPU-bound work would look like this:
// Documentation: This method is CPU-bound.
void DoWork();
Which you would call using Task.Run:
await Task.Run(() => DoWork());
Methods that are a mixture of CPU-bound and I/O-bound should have an Async signature with documentation pointing out their CPU-bound nature:
// Documentation: This method is CPU-bound.
Task DoWorkAsync();
Which you would also call using Task.Run (since it is partially CPU-bound):
await Task.Run(() => DoWorkAsync());
One issue with your ContentLoader is that internally it operates sequentially. A better pattern is to parallelize the work and then sychronize at the end, so we get
public class PageViewModel : IHandle<SomeMessage>
{
...
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
// makes UI very laggy, but still not dead
await this.contentLoader.LoadContentAsync();
HideLoadingAnimation();
}
}
public class ContentLoader
{
public async Task LoadContentAsync()
{
var tasks = new List<Task>();
tasks.Add(DoCpuBoundWorkAsync());
tasks.Add(DoIoBoundWorkAsync());
tasks.Add(DoCpuBoundWorkAsync());
tasks.Add(DoSomeOtherWorkAsync());
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
Obviously, this doesn't work if any of the tasks require data from other earlier tasks, but should give you better overall throughput for most scenarios.

Use async without await with a function that holds another function that returns void

So I have this WrapperFunction that tries to make a FunctionReturningVoid to be called asynchronously:
public async Task WrapperFunction()
{
this.FunctionReturningVoid("aParameter");
}
This is the function that returns nothing. In some parts of the code (not detailed here) it is called SYNChronously but in the CallerFunction() we want it to be run ASYNChronously.
public void FunctionReturningVoid(string myString)
{
Console.Write(myString);
}
This is the function that has the async implemented and needs to have WrapperFunction do its things without blocking otherStuff().
public async Task CallerFunction()
{
await WrapperFunction():
int regular = otherStuff();
...
}
The IDE is warning me that WrapperFunction is not using await:
This async method lacks 'await' operators and will run synchronously.
Consider using the 'await' operator to await non-blocking API calls,
or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Question: How to use async without using await in WrapperFunction? If I use await it tells me that cannot await void.
It's important to distinguish asynchronous from parallel.
Asynchronous means not blocking the current thread while you're waiting for something to happen. This lets the current thread go do something else while waiting.
Parallel means doing more than one thing at the same time. This requires separate threads for each task.
You cannot call FunctionReturningVoid asynchronously because it is not an asynchronous method. In your example, Console.WriteLine() is written in a way that will block the thread until it completes. You can't change that. But I understand that's just your example for this question. If your actual method is doing some kind of I/O operation, like a network request or writing a file, you could rewrite it to use asynchronous methods. But if it's doing CPU-heavy work, or you just can't rewrite it, then you're stuck with it being synchronous - it will block the current thread while it runs.
However, you can run FunctionReturningVoid in parallel (on another thread) and wait for it asynchronously (so it doesn't block the current thread). This would be wise if this is a desktop application - you don't want to lock up your UI while it runs.
To do that, you can use Task.Run, which will start running code on another thread and return a Task that you can use to know when it completes. That means your WrapperFunction would look like this:
public Task WrapperFunction()
{
return Task.Run(() => this.FunctionReturningVoid("aParameter"));
}
Side point: Notice I removed the async keyword. It's not necessary since you can just pass the Task to the calling method. There is more information about this here.
Microsoft has some well-written articles about Asynchronous programming with async and await that are worth the read.

Sync calling async nested methods - Will async work down the path?

I have async methods inside my libraries and the top level call is made at the handler of AWS Lambda functions synchronously (for some reason not to discuss here). I wonder if any calls made down the track be asynchronous by any chance? or because the first caller does it synchronously will everything be synchronous?
public void LambdaHandler(Input inp, ILambdaContext context)
{
method1().GetAwaiter().GetResult();
}
private async Task method1()
{
await method2();
await method3();
}
private async Task method2()
{
//do something
}
private async Task method3()
{
//do something
}
method2 and method3 will do whatever they always have done. If they are purely synchronous behind a Task API, then they will continue to be synchronous; if they are asynchronous, then they will continue to be asynchronous. The only question here is: what will LambdaHandler do, and the answer to that is simply:
it will block until they are complete
If they are already complete synchronously, then fine; if they aren't, then you've tied up a thread in a sync-over-async block. This could by itself cause a deadlock if your code uses a sync-context or task-scheduler that only has a single worker (which isn't uncommon), as the thread that the async code will need to do any post-processing will be stuck waiting at GetResult(). So the async part can't complete, and GetResult() can't complete.
You should avoid sync-over-async like the plague. There is a reason it is considered an anti-pattern.
The methods down below the call stack will run asynchronously.
But the entire thing would block and wait for the task to complete.
The better way is to modify LambdaHandler to return Task and use await instead of calling the GetAwaiter.
Help link

Difference between calling an async method and Task.Run an async method

I have a method in my view model
private async void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
this.SyncContacts();
}
}
private async Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
CloudInstance.AddContacts(contactsToUpload);
}
When I call SyncData from the UI commands and I'm syncing a large chunk of data UI freezes. But when I call SyncContacts with this approach
private void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
Task.Run(() => this.SyncContacts());
}
}
Everything is fine. Should not they be the same?
I was thinking that not using await for calling an async method creates a new thread.
Should not they be the same? I was thinking that not using await for
calling an async method creates a new thread.
No, async does not magically allocate a new thread for it's method invocation. async-await is mainly about taking advantage of naturally asynchronous APIs, such as a network call to a database or a remote web-service.
When you use Task.Run, you explicitly use a thread-pool thread to execute your delegate. If you mark a method with the async keyword, but don't await anything internally, it will execute synchronously.
I'm not sure what your SyncContacts() method actually does (since you haven't provided it's implementation), but marking it async by itself will gain you nothing.
Edit:
Now that you've added the implementation, i see two things:
I'm not sure how CPU intensive is your synchronous data analysis, but it may be enough for the UI to get unresponsive.
You're not awaiting your asynchronous operation. It needs to look like this:
private async Task SyncDataAsync(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
await this.SyncContactsAsync();
}
}
private Task SyncContactsAsync()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
return CloudInstance.AddContactsAsync(contactsToUpload);
}
What your line Task.Run(() => this.SyncContacts()); really does is creating a new task starting it and returning it to the caller (which is not used for any further purposes in your case). That's the reason why it will do its work in the background and the UI will keep working. If you need to (a)wait for the task to complete, you could use await Task.Run(() => this.SyncContacts());. If you just want to ensure that SyncContacts has finished when you return your SyncData method, you could using the returning task and awaiting it at the end of your SyncData method. As it has been suggested in the comments: If you're not interested in whether the task has finished or not you just can return it.
However, Microsoft recommend to don't mix blocking code and async code and that async methods end with Async (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx). Therefore, you should consider renaming your methods and don't mark methods with async, when you don't use the await keyword.
Just to clarify why the UI freezes - the work done in the tight foreach loop is likely CPU-bound and will block the original caller's thread until the loop completes.
So, irrespective of whether the Task returned from SyncContacts is awaited or not, the CPU bound work prior to calling AddContactsAsync will still occur synchronously on, and block, the caller's thread.
private Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// ** CPU intensive work here.
}
// Will return immediately with a Task which will complete asynchronously
return CloudInstance.AddContactsAsync(contactsToUpload);
}
(Re : No why async / return await on SyncContacts- see Yuval's point - making the method async and awaiting the result would have been wasteful in this instance)
For a WPF project, it should be OK to use Task.Run to do the CPU bound work off the calling thread (but not so for MVC or WebAPI Asp.Net projects).
Also, assuming the contactsToUpload mapping work is thread-safe, and that your app has full usage of the user's resources, you could also consider parallelizing the mapping to reduce overall execution time:
var contactsToUpload = this.AllContacts
.AsParallel()
.Select(contact => MapToUploadContact(contact));
// or simpler, .Select(MapToUploadContact);

Categories

Resources