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.
Related
I haven't used async/await very often and I'm not fully comfortable with them. I am trying to make an operation that is synchronous to be run asynchronously. Can you tell me if the following code snippet makes sense:
public static async Task<string> FileVersionAsync(string localFilePath)
{
FileVersionInfo versionInfo;
try
{
versionInfo = await Task.FromResult(FileVersionInfo.GetVersionInfo(localFilePath));
}
catch (SecurityException)
{
return "File Version Checker does not have permission to read file version";
}
catch (FileNotFoundException)
{
return "Unable to find configured file";
}
if (versionInfo.FileVersion == null)
return "N/A";
return versionInfo.FileVersion;
}
Adding Task, await and async do not make something asynchronous; they merely provide the plumbing to work with asynchronous code when it happens. In your example: it never happens asynchronously, so all you are doing is adding plumbing overhead for no benefit.
The compiler will generate a ton of extra code that will turn out to never be hit, because when it gets to the await it'll discover that the task is already complete, and will simply continue on the existing thread.
To actually be asynchronous, you need ... something that is async. This could be external IO, or could be something threading related - but note that simply jumping to another thread doesn't buy you anything: it just adds a context switch.
If there was a FileVersionInfo.GetVersionInfoAsync method, what you are doing might be worthwhile.
No it does not make sense.
The only reason to make your function async is if somewhere inside it awaits other functions that are async. In fact your compiler warns you if you forget to await somewhere.
The async-await syntax was invented as a replacement for other task functions like Task.ContinueWith, Task.FromResult, Task.FromException etc.
In this interview Eric Lippert compared async-await with a cook who has to prepare breakfast Search somewhere in the middle for async-await.
If a cook has to prepare breakfase he starts to boil water. But instead of waiting for the water to cook, he starts slicing bread, and do other things. Only after he has nothing to do anymore he starts waiting idly for the water to boil after which he makes the tea.
Similarly: if a program has to wait for an external process to perform a request, like a database query, write data to a file, get information from the internet etc. async-await makes sure that your thread doesn't wait idly. Instead your thread goes up its call stack to see if one of the callers can continue working without the result from the other process.
You'll see this in the following code:
public async Task<string> ReadTextFile()
{
StreamReader txtReader = File.OpenText(...);
// read the complete text file; don't wait until finished yet
Task<String> taskTxt = txtReader.ReadToEndAsync();
// as we didn't use await, we can continue processing:
DoSomething();
// now we need the result from the read action: await for it
// the result of await Task<TResult> is the TResult:
string importedTxt = await taskTxt;
return importedTxt;
}
Some guidelines for async-await:
Only use async-await if you call at least one other async function
instead of void return Task, instead of TResult return Task<TResult>
Only exception: the async event handler: this async function returns void
The return of await Task is void; the return of await Task<TResult> is TResult
If you don't need the result of an async function right now, and if you can do something meaningful while the task is processing: start the task by calling the async function, but don't await for it. Only await when you need the result
.
public async void Button_Clicked(object sender, EventArgs e)
{
// indicate you will do something time consuming:
this.ProgressBar1.Visible = true;
await DoSomethingTimeconsumingAsync(...);
// finished:
this.progressBar1.Visible = false;
}
This will make sure that whenever your thread has to wait something, it can do other things, and thus your GUI remains responsive.
No. There appears to be absolutely no need to make this method async, because Task.FromResult is ready immediately.
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.
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
}
I am so confused with the following methods. Which one is the best and why? These are working fine.
public string GetString(int i)
{
return "Testing number " + i.ToString();
}
//async methods where I'm confused with
public Task<string> GetStringAsync(int i)
{
return Task.FromResult<string>(GetString(i));
}
//Or
public Task<string> GetStringAsync(int i)
{
Task<string> task = new Task<string>(() => GetString(i));
task.Start();
return task;
}
//Or
public Task<string> GetStringAsync(int i)
{
var tcs = new TaskCompletionSource<string>();
tcs.SetResult(GetString(i));
return tcs.Task;
}
The caller will be
Task<string> task = SomeClass.GetStringAsync(9);
Console.WriteLine(task.Result);
//Or
var result = await SomeClass.GetStringAsync(9);
Console.WriteLine(result);
Thank you so much.
I think you may not fully understand why anyone would want to use async. Async .Net allows the freeing up of threads that would normally be waiting on some external action to take place (network call or hard disk call). Normally windows uses I/O Completion Ports for these calls and has recently added async/await keywords to allow .Net access to native asynchronous calls. That being said there is a little overhead when using async as the runtime has to create a state-machine to keep track of a threads current state before assigning the await'd thread a new task.
Thus any async tasks that aren't using a I/O Completion Port are most likely doing more harm than good.
//async methods where I'm confused with
public Task<string> GetStringAsync(int i)
{
return Task.FromResult<string>(GetString(i));
}
Well let me correctly code this into an async method:
//async methods where I'm confused with
public async Task<string> GetStringAsync(int i)
{
return await Task.FromResult<string>(GetString(i));
}
Still bad, because there is no reason to use async; unless I'm mistaken about how Task.FromResult() works, this has additional overhead for no benefit.
I'm just going to rewrite them all as async and then give my understanding of what affect they have.
public async Task<string> GetStringAsync(int i)
{
Task<string> task = new Task<string>(() => GetString(i));
await task.Start();
return task;
}
It's extremely rare that you should be creating and starting your own tasks, it's not a good idea.
public Task<string> GetStringAsync(int i)
{
var tcs = new TaskCompletionSource<string>();
tcs.SetResult(GetString(i));
return tcs.Task;
}
The TaskCompletionSource was primarily designed to wrap current asynchronous into the async/await pattern. Since this isn't wrapping any type of asynchronous action there is no performance benefit.
public string GetString(int i)
{
return "Testing number " + i.ToString();
}
This is your best bet. Don't use async/await unless you actually need to.
Stephen Cleary has a great set of Posts that talk about Tasks and Async, I highly recommend you read through it before diving into Async in .Net.
Actually, none of the above are correct.
public Task<string> GetStringAsync(int i)
{
Task<string> task = new Task<string>(() => GetString(i));
task.Start();
return task;
}
should actually be:
public async Task<string> GetStringAsync(int i)
{
return await Task.Run(() => GetString(i));
}
Note, in particular, the use of the "async" keyword (which enables the use of the "await" keyword; "await" is the equivalent of "come back to me when I have a result for you," see the documentation for details of the state machine that this creates). The examples you provide reflect an older way of doing task parallelism that is no longer a best practice.
An important note at this point: make sure it's the case that GetString is a CPU-bound task. There are several kinds of async methods: ones that run asynchronously in the same thread (which are primarily used for IO-bound tasks), ones that run in the thread pool (which are used primarily for CPU-bound tasks), and ones that shouldn't be async in the first place (things that are neither CPU-bound or IO-bound).
My standard illustration of this fact is as follows: suppose you go a restaurant with 10 people. When the waiter comes by, the first person he asks for his order isn't ready; however, the other 9 people are. Thus, the waiter asks the other 9 people for their orders and then comes back to the original guy hoping he'll be ready to order by then. (It's definitely not the case that they'll get a second waiter to wait for the original guy to be ready to order and doing so probably wouldn't save much time anyway). That's how async/await works in many cases (the exception being that some of the Task Parallel library calls, like Thread.Run(...), actually are executing on other threads - in our illustration, bringing in a second waiter - so make sure you check the documentation for which is which).
Thus, when you're using async/await, make sure you know whether something is CPU-bound (and therefore appropriate for executing on a separate thread), IO-bound (and therefore appropriate for asynchronous execution in the same thread), or neither (and therefore pointless to make async in the first place).
I am abit confused when it comes to how a method should look like when dealing with async / task.
From my understanding, a method that just creates a new task doesnt need to be async since this would produce overhead as it wraps the hole thing in a new task.
So this:
async Task _doStuff()
{
await Task.Run(()=> _stuff());
}
Is better this way:
Task _doStuff()
{
return Task.Run(()=> _stuff());
}
However, it gets a bit more complicated, if there are some preconditionchecks
Which way is better then?
async Task _doStuff()
{
if(stuffWasDone)
return;
await Task.Run(()=> _stuff());
}
or
Task _doStuff()
{
if(stuffWasDone)
return Task.Run(()=> {}); // this could be a static-readonly in some helper like AsyncHelper.Empty(); as there is no FromResult for Task.
return Task.Run(()=> _stuff());
}
You dont have to use Task.Run in order to generate a Task. A Task is a promise.
If a Task doesn't need to execute, don't create one. Using Task.Run has the overhead of invoking an empty lambda on a threadpool thread, you don't need that. Simply returning should suffice.
You may also use Task.FromResult if no Task is actually needed:
Task DoStuffAsync()
{
if(stuffWasDone)
{
return Task.FromResult(0);
}
return Task.Run(() => _stuff());
}
If you don't want to re-generate the Task over again, you can simply put it in a local variable:
private static Task _emptyTask = Task.FromResult(0);
As for your first example of await vs return await, you cannot say one is "better" then the other, as they serve different purposes. The former will asynchronously wait for the Task to complete before returning while the latter will return a hot task to the caller. This will matter in regards of exception handling. More so, if you're not going to be consuming the result of the task afterwards, using await will incur in a redundant generation of a state machine.
As another side note, wrapping synchronous methods in asynchronous wrappers is bad practice. Let the end user explicitly call Task.Run instead, don't fool them with async behavior.