How to create an awaitable method properly - c#

I am writing some awaitable methods and I found a lot of way to do so on the internet. So I came here to know what is really happening on each way, and if some ways must be banished.
As far as I know, there is two kind of awaitable methods:
Those which call other awaitable methods :
public async Task<Foo> GetFooAsync()
{
var foo = await TrulyGetFooAsync();
// Do stuff with foo
return foo;
}
I did not find any other way to do this and I think it is the right way. Tell me if I am wrong !
Those which only call non-awaitable methods :
And here the problems come in my mind.
For example, I saw this:
Exemple 1
public async Task<Foo> GetFooAsync()
{
return await Task.Run(() => TrulyGetFoo());
}
As far as I understand, the async/await keywords are useless and can be avoided to give this:
Exemple 2
public Task<Foo> GetFooAsync()
{
return Task.Run(() => TrulyGetFoo());
}
This last example is what I was doing until now. About that, is there a difference between:
Task.Run(() => TrulyGetFoo());
and
Task.Run((Foo)TrulyGetFoo); // I don't know if the cast is required at any time but in my code, it was
???
But I recently found this way:
Exemple 3
public Task<Foo> GetFooAsync()
{
TaskCompletionSource<Foo> tcs = new TaskCompletionSource<Foo>();
tcs.SetResult(TrulyGetFoo());
return tcs.Task;
}
If I understood properly, an awaitable method does not always run on another thread ??? My guess is the third example is providing this mecanism (but how ??? I only see synchronous code in the third example), when the examples 1 and 2 will always run on a worker thread ???
May be there is still another ways to write awaitable methods, so let me know about them.

For example, I saw [Task.Run wrappers around synchronous code]
This is a bad practice. I have a blog post that explains why Task.Run should not be used as a method implementation.
As far as I understand, the async/await keywords are useless and can be avoided
Yes, but I don't recommend eliding async/await in more complex methods.
I recently found [TaskCompletionSource<T>]
As noted in the comments, your code example is still synchronous.
To make it asynchronous, your code should start some operation and return TaskCompletionSource<T>.Task. Then later, whenever that operation completes, your completion handler should call TaskCompletionSource<T>.SetResult (or similar method). For an example, see TAP wrappers for EAP or TAP wrappers for WaitHandles.
TaskFactory.FromAsync is also a wrapper around TaskCompletionSource<T>, and is used for TAP wrappers for APM.

The short version is this: anything that returns a Task can be awaited inside an async code block.
public async Task MyAsyncMethod()
{
// do some stuff
await TrulyAsyncFoo();
// do some other stuff
return;
}
If awaiting the async call is the only thing the method does, you can simply return the task itself, which will be awaited "upstream":
public Task MyAsyncMethod()
{
return TrulyAsyncFoo();
}
As far as calling synchronous (non-async) code in an async method, there's nothing to it. Just call it like normal code:
public async Task MyAsyncMethod()
{
MySyncMethod();
await TrulyAsyncFoo();
MyOtherSyncMethod();
}
Doing Task.Run(() => Foo()) is almost always a code smell that you aren't doing async/await right. Writing async code is not the same thing as writing multithreaded code. Async is just a nice way of telling the compiler that you need to wait for some network- or IO-bound task to complete.
To sum up:
Await lets you write asynchronous and synchronous code side-by-side
Async should only be used to wait for network- or IO-bound tasks, not compute-bound tasks
Async methods should always return Task or Task<T>
Avoid async void
Avoid blocking using task.Wait() and task.Result in ASP.NET and other threaded applications unless you know what you are doing

I am using this for async events that manipulate my DB
private async void btnSave_Click(object sender, EventArgs e)
{
success = await someClass.someMethod(some args);
}
and the someMethod is a task like that:
public static async Task<someObject> someMethod(args)
{
//do something here
}

Related

Is awaiting methods from synchronous sources with await Task.Run(() => good practice?

I have a method that has the async keyword with a task. This method returns a string that comes from JwtSecurityTokenHandler().WriteToken(t); The thing is none of the assignments in the body of the method are awaitable.I get the warning CS-1998. That says you shouldnt use async for synchronous methods which makes complete sense. But then it adds that you can use await Task.Run(() => { . So is it good practice to do this?
public async Task<object> GenerateMyUserJwtToken(string email, IdentityUser user)
//code that isnt awaitable
{
var u = await Task.Run(() =>
{
return new JwtSecurityTokenHandler().WriteToken(token);
});
return u;
}
edit: I did not ask what the error was I asked if it was a good idea to Implement await Task.Run(() on an async method signature that has no await assignments. I also asked that another async method is awaiting this in the another method here is the code
//awaiting method:
public async Task<object> LoginAsync(LoginDto model)
{
return await GenerateMyUserJwtToken(model.Email, appUser);
}
//controller:
[HttpPost("login")]
public async Task<object> Login([FromBody] LoginDto model)
{
var logMeIn = await new AuthUserService().LoginAsync(model);
return logMeIn; //returns token
}
My Question is is this async all the way or does the task.Run stop that process?
Using Task.Run just to make something sync is generally a bad practice but it cannot be stated generally.
If the sync method to execute may take for a long time, then it can be a solution. Please note that Task.Run will assign the task to a pool thread and it is not always desirable. It is a common misunderstanding that async methods always use or should use threads somewhere at the end of the async-await chain. However, async-await has nothing to do with threads, it is about asynchronicity (chaining deferred tasks) and creating threads is just one option to create awaitable tasks.
So what are the options?
The method to call is fast and never blocks the caller for long time (>100ms or so): do not use async at all. In this case Task<T>.FromResult(result) is a tempting solution but is highly discouraged because it is misleading for the caller. Use it only in unit tests or if you are forced to implement an async method of an interface you cannot change.
The method execution takes for a long time because it is CPU bound: now you can use a thread. But I typically would not use pool threads for long lasting tasks as it can cause nasty side effects if the thread pool is out of threads. Use await Task.Factory.StartNew(() => MyLongRunningTask(), cancellationToken, TaskCreationOptions.LongRunning); instead, which creates a brand new thread instead of bothering the pool.
The method execution takes for a long time because it is IO bound (eg. sending/receiving packets via a hardware): Use TaskCompletitionSource<T>, add a hook to the whatever completition event of the device (eg. OS hook or IRQ notification) and from that set the result of the completition source and return its task.

Making async method properly

I googled a lot and for the moment the only async implementation I found (including MSDN site) is the following:
public async void Foo()
{
...
await StreamReader.ReadAsync();
...
}
So in all the cases they use some method which is already async. And this is not what I need.
Let's say that I have a heavy method that does something:
public void DoSomthing()
{
...
}
And there is method where I call this DoSomething:
public void MajorMethod()
{
DoSomething();
}
I want to make DoSomething ayncthonous and call it.
The only solution I see would be the following one:
public Task MajorMethod()
{
return Task.Run(()=>DoSomething());
}
But I read some comments that it's not really the async. So how can I make DoSomething async?
If the MajorMethod has no other things to do other than calling the DoSomething, your code is fine.
But if you need to do other stuff after calling to DoSomething, then mark MajorMethod as async, and use await before Task.Run
public async Task MajorMethod()
{
await Task.Run(()=>DoSomething());
//stuff in here will executed after DoSomething completed
}
Examples from MSDN: Asynchronous programming
or just google c# async
You should be clear about the role async/await play in the Task Asynchronous Pattern. Making an async method does not parform an operation asynchronously just like that. Marking an existing method async will not magically perform everything in there asynchronously. Its main effect is that now you are allowed to use await within the method (I read that it even was discussed if the async keyword was necessary at all; it was added to avoid a breaking change when a local variable in existing methods would be named await).
await also does not provide asynchrony by itself, it provides a way to synchronize to another asnychronous method and yield while the other operation is still running. You can await another async method, but unless somwhere down the chain there is an actual Task running in another thread, the async method might even return synchronously.
In consequence this means that you need an operation that runs asynchronously first (such as a DB query, file access, network communication) and from there you create a chain of async methods that await the previous method.
Now in your case, when you have a computationally intensive method that does not wait for external resources, you can choose to perform the operation asynchronously. Since modern CPUs usually have more than one core at your disposal, you can increase both, performance and application responsiveness like that. The method would not be async, since it does not await anything:
void DoSomething()
{
//...
}
Task DoSomethingAsync() {
return Task.Run(DoSomething);
}
All callers of DoSomethingAsync can now use await to synchronize with this operation running in the background (note the change in return type to Task to allow callers to await):
async Task MajorMethod() {
//...
await DoSomethingAsync();
//...
}
This would allow callers of MajorMethod to synchronize with it. What you can also do is to do stuff in MajorMethod while DoSomethingAsync is running (and still await to allow callers to do even more parallel operations):
async Task MajorMethod() {
//This part will run before DoSomethingAsync
//...
Task doSomethingTask = DoSomethingAsync();
//This part is executed at the same time as DoSomethingAsync
//...
await doSomethingTask; //Here the caller can do more operations while DoSomething is running
//This part will be executed after DoSomethingAsync has finished
//...
}
This form of acquiring a task, doing something and only then awaiting the task has to be done somewhere in the chain, otherwise you have no benefit from the asynchronous operation. Even though this might be an overgeneralization, since synchronization can happen in more subtle ways, for example with a custom synchronization context. But as far as your question is concerned, you should go with: There is an actual task on one end and something that is done after the async call, but before the await on the other end.

Async/await: a correct way to make background task non-blocking

EDIT: from OP's comment, the goal is
non-blocking background task so that the rest remain responsive
Say I have a function like this:
void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
ProcessAsynchronously(_latestImageBytes);
//some more code here
}
In the point commented, I want to introduce a call to an asynchronous function.
Now, I can not modify OnFrameSampleAcquired (meaning I can not make it "async").
How can I do this?
I am thinking
async void ProcessAsynchronously(byte[] image)
{
await Process1(image);
await Process2(image);
// ...
}
or async Task ProcessAsynchronously(byte[] image)
where ProcessX are also declared as async
Is this a good approach?
Thanks for any insight, since my practical experience with asynchronous processing is very few.
EDITED included all suggestions from the comments and added some background.
Background & insights
Converting one function to async won't be enough to make the whole process non-blocking. To achieve what you want, the whole processing path (call stack) should be converted to non-blocking. One blocking method on your call stack is enough to render the whole process blocking. Non-blocking does not necessarily mean async, as some of the examples below will show.
There are two steps involved in converting a method into async:
Change the signature to return Task. This will allow your callers track status and outcome of your method.
Add async keyword to the signature. This will allow await-ing other async methods in the body of your method.
CPU-bound vs IO-bound tasks
Note that even when you await for a method, it doesn't necessarily mean that you immediately release the thread back to your caller. The method being await-ed will release the thread back to you only as soon as it in turn begins await-ing for an IO-bound operation. Your thread will still block while the await-ed method performs CPU-bound operations before the first time it is await-ing for an IO-bound operation.
For example:
async Task MyAsyncMethod()
{
Thread.Sleep(5000); // equivalent to CPU-bound operations
}
await MyAsyncMethod(); // will block for 5 seconds
On the other hand,
async Task MyAsyncMethod()
{
await Task.Delay(5000); // equivalent to IO-bound operations
}
await MyAsyncMethod(); // will return immediately
And the workaround if you have CPU-bound tasks but still don't want to block the caller thread:
async Task MyAsyncMethod()
{
await Task.Yield(); // this does the magic
Thread.Sleep(5000); // equivalent to CPU-bound operations
}
await MyAsyncMethod(); // will return immediately thanks to Task.Yield()
What to do in your case
Since I'm not sure why you cannot change OnFrameSampleAcquired signature to async, I will suggest several different options.
Option 1
The simplest and the truly asynchronous approach would be this:
async Task OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
await ProcessAsynchronously(_latestImageBytes);
//some more code here -- provided it is either async or non-blocking!
}
async Task ProcessAsynchronously(byte[] image)
{
await Process1(image);
await Process2(image);
// ...
}
If all of the methods on your processing path look like these, you have a properly implemented non-blocking background job.
Option 2
If you're absolutely unable to change the signature OnFrameSampleAcquired, there is a workaround. You can instead invoke the rest of the processing asynchronously, as suggested by #Fildor:
public void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
ProcessAsynchronously(_latestImageBytes).ContinueWith(task => {
// this runs on a different thread after ProcessAsynchronously is completed
// some more code here
});
// return without blocking
}
Here you win on both sides: first, you don't have to change the signature of OnFrameSampleAcquired; second, OnFrameSampleAcquired is now a non-blocking method.
Option 3
If you cannot change your signature because you must implement an interface like this:
public interface ISomeInterface
{
void OnFrameSampleAcquired(VideoCaptureSample sample);
// ... other members
}
then you can add the async keyword to your method and still comply with the interface:
async void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
await ProcessAsynchronously(_latestImageBytes);
//some more code here
}
ISomeInterface x; // initialized elsewhere
x.OnFrameSampleAcquired(/*....*/); // the same as await, but no error handling
The drawback of this option is that the callers cannot track nor the status of the task (still running or completed?), neither its outcome (completed or threw exception?). You will probably have to wrap the entire body of OnFrameSampleAcquired in a try/catch, and write an exception to log.
Option 4
Technically, you can also invoke an async ProcessAsynchronously from a non-async OnFrameSampleAcquired using Wait on a Task, but it won't achieve your goal of having a non-blocking background task. The Wait() will block the thread until the async processing is done:
void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
ProcessAsynchronously(_latestImageBytes).Wait();
//some more code here
}

Difference in task processing

Let's suppose that I Have two methods, like this...
public void MyMethod()
{
// do some stuff
}
public Task MyMethodAsync()
{
//run MyMethod asynchronously
}
What is the best form to execute it in async way?
Like this
public Task MyMethodAsync()
{
return Task.Run(() => MyMethod());
}
or like this?
public async Task MyMethodAsync()
{
await Task.Run(() => MyMethod());
}
You should read Stephen Cleary's tutorial on when -- and when not -- to use Task.Run.
Short answer: don't use Task.Run to create a fake async method. If your code isn't truly async, then let the caller decide if it should use a thread (or whatever) to call your code.
In the case of your first method, you may as well just have a task on a separate thread. It's not really async because you aren't clearly waiting for the thread to end to start a new process. If you called this it would continue before the task was complete.
public Task MyMethodAsync()
{
return Task.Run(() => MyMethod());
}
Looking at the second version. You are waiting for the task to complete so that you can do something after without holding up the current thread.
public async Task MyMethodAsync()
{
await Task.Run(() => MyMethod());
DoMoreWork();
//Do something following the completion of the task
//without binding up the calling thread, but actually complete it on that thread.
}
It's better to go the other way around. Build the inner task as async, and then let all the callers who can't use the async method use the async one internally and wait on it.
public void MyMethod()
{
MyMethodAsync().Wait();
}
public async Task MyMethodAsync()
{
// do some stuff
}
Both of your methods aren't truly making anything async. Async isn't about running something in the background, that's the realm of the Task library (or parallel extensions, or threading, etc). Async is about being able to re-use a single thread for multiple things when it has nothing better to do -- which makes thing more scalable. Making a pseudo-async method is just hiding the fact that you are using a NEW thread instead of reusing the same thread, which makes the system LESS scalable.
In order to do that, true async processes need to be written that way from the inside out. Everything (or at least the parts that are time consuming) need to rely on async methods that do that. For example, making a SOAP call where the thread is going to basically just sit idle while waiting for the call to return, or a database call, or file I/O. Async allows that thread to go do something else useful instead of just sitting idle.

Async/Await Execution Difference

I'm trying to get a good grasp of async/await and I want to clear some of the confusion. Can someone please explain what would be the difference in terms of execution for the following:
// version 1
public Task Copy(string source, string destination) {
return Task.Run(() => File.Copy(source, destination));
}
public async Task Test() {
await Copy("test", "test2");
// do other stuff
}
And:
// version 2
public async Task Copy(string source, string destination) {
await Task.Run(() => File.Copy(source, destination));
}
public async Task Test() {
await Copy("test", "test2");
// ...
}
Are they resulting in the same code and why would I write one over the other ?
First of let me start with the point that both codes are not same.
Your version1 code will create only one "State machine" as it contains await in Test method only.
Your version2 code will create two "state machines" for Copy and Test method which adds some overhead.
Why do we use async methods? Simple just to make our code readable, elegant while dealing with "Asynchronous Tasks". It makes our code better avoiding callbacks and continuations etc.
Let's break down what Copy method is doing and we answer the
question whether we really need it to be async?
Copy method simply delegates the call to Task.Run which returns a task that eventually reaches completion on File.Copy's completion. So the intent is clear here we need a task which notifies File.Copy completion. This method does all what you need, no need for it to be async to work as expected.
So, When do you need async?
You need async when you need to execute some code upon earlier task's completion(Continuation).
Example:
public async Task Test()
{
await Copy("test", "test2");
DoPostCopied(whatever);
await DoPostCopied2();//Etc
}
You can verify this difference between async and non async method just by decompiling both versions. It is too long and won't be readable so I skipped posting it here.
Conclusion: Use async only when required. In this case version1 is better and you should prefer it over version2.

Categories