Should I omit async / await if possible? - c#

I have a method which takes long to run: it calls the DB and makes certain calculations synchronously:
public static MyResult MyMethod(int param1, int param2)
{
// run a DB query, wait for result, make calculations...
...
}
I want to write a wrapper for it, to be able to use it from my WinForms UI with 'await' keyword. To do this, I create another method, MyResultAsync. I have a choice, how exactly to write it:
// option 1
public async static Task<MyResult> MyResultAsync(int param1, int param2)
{
return await TaskEx.Run(() => MyMethod(param1, param2));
}
// option 2
public static Task<MyResult> MyResultAsync(int param1, int param2)
{
return TaskEx.Run(() => MyMethod(param1, param2));
}
So, which option is preferable and why? As you can see, the difference is just in presence/absence of 'async' and 'await' keywords.
Thank you!

Use the second option.
Your first option creates a Task<MyResult>, and then creates another Task<MyResult> to wrap it. The wrapping doesn't add any value, just overhead.
Stephen Toub has a great video from BUILD called The Zen of Async: Best Practices for Best Performance, which covers the async/await overhead and alternatives.

Its all about how async actually works. If you read http://msdn.microsoft.com/en-us/magazine/hh456402.aspx and in particular: http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229662.aspx you'll find that the async keyword makes the compiler build a statemachine within your code. This is overhead and for performance sake, will perform worse since it's absolutely not required in the code given.
As for readability: I should use async only where it really can make a difference. async for me means that a certain method finishes in multiple steps in an async manner. When you define a simple proxy method like the above, you dont want to complicate the syntax any further.

Related

Returning from async methods

I have a async method returning a task. Do I need to return anything in the following situation?
public async Task UpdateProductSpecificationsAsync()
{
await _productRepository.UpdateProductSpecificationsAsync(); //Takes long time to execute
}
Is the following code examples equivalent to each other?
public Task UpdateProductSpecifications()
{
_productRepository.UpdateProductSpecifications(); //Takes long time to execute
return Task.FromResult(0);
}
public Task UpdateProductSpecifications()
{
_productRepository.UpdateProductSpecifications(); //Takes long time to execute
return Task.CompletedTask;
}
Is there any situation where I should await a Task.TaskCompleted?
I have a async method returning a task. Do I need to return anything in the following situation?
An async Task method is equivalent to a non-async void method. And like a non-async void method, an async Task method can't return anything.
That said, your example seems odd. If all you're going to do in the method is await some other async method, you should not bother with the async/await at all. Just return the Task directly:
public Task UpdateProductSpecificationsAsync()
{
return _productRepository.UpdateProductSpecificationsAsync();
}
Is the following code examples equivalent to each other?
Define "equivalent". To me, they are definitely not equivalent. The first creates a new Task<int> object, and returns that object as a Task. Calling code would have to cast it back to Task<int> to see the result value.
The second returns the static Task.CompletedTask property value, which is a singleton object, allocated only once per process. There is no result value for the caller to read.
The caller would have to go to extra work to directly observe those differences, but at the very least, returning a reference to a singleton object is more efficient than creating a new object every time. Whether this is significant or not depends, of course, on how often you call the method.
All that said, I don't understand why in that scenario, you wouldn't implement it like this (assuming there's no truly asynchronous version of the _productRepository method):
public Task UpdateProductSpecificationsAsync()
{
return Task.Run(() => _productRepository.UpdateProductSpecifications());
}
Then you'd get actual asynchronous behavior, which is what the caller would typically expect. Your versions force the caller to wait in spite of the method looking like it's asynchronous. IMHO, it's a very bad idea to write code that lies.
Is there any situation where I should await a Task.TaskCompleted [sic]?
You mean directly? Or by code that doesn't know it's been handed the Task.CompletedTask reference? I'm going to assume the former, because it's unreasonable to expect the latter to have any idea that's what it's doing.
That seems like an overly broad question to me. Any situation? That's open to interpretation.
That said, I would say "no" to that question. What would the point of awaiting something you know is already completed? The await won't yield back to the caller, because the awaitable is already completed. It seems like a waste to me.
I can imagine scenarios where one awaits a Task.CompletedTask in order to achieve some other desired side-effect. I've seen weirder things than that in production code. But I wouldn't recommend it. Whatever hypothetical side-effect we'd be talking about, I'm sure it's not a documented side-effect, so one would be relying on undocumented implementation details that could change in the future.
Don't write fragile code. Write code that relies only on documented behavior, and only does things that make obvious sense. (And the corollary: if you break that rule, at the very least write a very detailed comment explaining why you wrote weird, fragile code.)

Can we turn async methods into expression body?

I was reading this article about Expression Bodied Members in C# 6.0, the author demonstrated this code:
public async Task<string> ReadFromWeb() => await RunWebRequest();
He says that it's not recommended to use async and await keywords in above code:
The compiler is performing some heavy lifting to implement the async
state machine for this method. Because of the structure of the method,
that extra work isn't really accomplishing much. It's creating a state
machine to wrap a task that simply unwraps a task returned from a
different method.
He proposed that we should write the code without async and await:
public Task<string> ReadFromWebSimple() => RunWebRequest();
I'd like to know more information about that.
Lets see what the author was talking about. When you mark a method as async, the compiler generates a state-machine on your behalf in order to allow the asynchronous style of execution to "feel like" it's executing synchronously.
When you write:
public async Task<string> ReadFromWeb() => await RunWebRequest();
The compiler generates:
[AsyncStateMachine(typeof(C.<RunWebRequest>d__1))]
public Task<string> RunWebRequest()
{
C.<RunWebRequest>d__1 <RunWebRequest>d__;
<RunWebRequest>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create();
<RunWebRequest>d__.<>1__state = -1;
AsyncTaskMethodBuilder<string> <>t__builder = <RunWebRequest>d__.<>t__builder;
<>t__builder.Start<C.<RunWebRequest>d__1>(ref <RunWebRequest>d__);
return <RunWebRequest>d__.<>t__builder.Task;
}
Since you're using an Expression Bodied Method, you actually have a single liner of a method. When do you generally await on something? when you want to manipulate the return value of the async method. With one-liners, that's never the case. This means that you can save the state-machine generation at the invocation level, and let only those who want to acutally await the result higher up the caller stack to await on your method. This will effectively transform your method to look like this:
public Task<string> ReadFromWeb()
{
return this.RunWebRequest();
}
Which saves you the rather already slim state-machine struct allocated by the compiler, which is actually quite redundant when you're creating an EBM.
Making a method async allows you to use await inside it. You don't really need await as you're not using the return value and you're not doing anything after that operation completes. In this case you can just return the task directly instead. That way your caller awaits the inner async method without the overhead of the method in between.
This avoids the work being done to make ReadFromWeb an async method. It's not a huge deal but in this case where all you have is a single invocation doing that is pretty harmless.

c# 5 async as a sugar syntax (or not)?

So I was asking this question about async , and I thought that it it's just a sugar syntax for :
Task<..>...ContinueWith...
And finally inspect the Result property.
I even asked a question about it here and I was told :
But Today I was corrected by Jon Skeet
" It's a very long way from that".
So what are the core differences between those 2 approaches ?
It is adding a continuation - but manually constructing that continuation can be very painful, due to the need to carry around all the information about where we'd got to and what the local state is.
As a very simple example, I suggest you try to come up with the equivalent of this async method:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
// These are just examples - you don't need to translate them.
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Really try to come up with the equivalent of the first method. I think you'll find it takes quite a lot of code - especially if you actually want to get back to an appropriate thread each time. (Imagine code in that async method also modified a WPF UI, for example.) Oh, and make sure that if either of the tasks fails, your returned task fails too. (The async method will actually "miss" the failure of the second task if the first task also fails, but that's a relatively minor problem IMO.)
Next, work out how you'd need to change your code if you needed the equivalent of try/finally in the async method. Again, that'll make the non-async method more complicated. It can all be done, but it's a pain in the neck.
So yes, it's "just" syntactic sugar. So is foreach. So is a for loop (or any other kind of loop). In the case of async/await, it's syntactic sugar which can do really rather a lot to transform your code.
There are lots of videos and blog posts around async, and I would expect that just watching/reading a few of them would give you enough insight to appreciate that this is far from a minor tweak: it radically changes how practical it is to write large amounts of asynchronous code correctly.
Additionally, being pattern-based, async/await doesn't only work on Task / Task<T>. You can await anything which adheres to the awaitable pattern. In practice very few developers will need to implement the pattern themselves, but it allows for methods like Task.Yield which returns a YieldAwaitable rather than a task.

Asynchronous method that does nothing

I have an interface IAnimation which exposes a method BeginAsync(). That method should start the animation and return when it is completed.
What I would like to do is implement a null animation class NoAnimation that just returns when it executes BeginAsync().
Is this the right implementation?
public async Task BeginAsync()
{
await Task.Run(() => { });
}
I suspect that there is a more elegant approach than this. I also considered
creating an empty method. But that gives me a warning which I don't like either.
Just use Task.CompletedTask to return a completed task:
public Task BeginAsync()
{
return Task.CompletedTask;
}
If you have a Task<TResult> use Task.FromResult<TResult> to return a completed task with a result:
public Task<bool> BeginAsync()
{
return Task.FromResult(true);
}
Your current implementation is very inefficient, as it builds the state machine, and also uses a ThreadPool thread to run the empty task.
I appreciate this doesn't exactly answer the original question (or at least not in a way that isn't already in another answer). What it does it provide additional context for #ReedCopsey's answer, for those (including me! and others, based on the comments on that answer) who initially might find it hard to understand what is going on here.
It's very easy to fall into the trap of thinking that async must be part of the signature of any asynchronous method. It looks as if it must be; it (misleadingly!) reads as if it's whole purpose is to mark a method as asynchronous.
But it's not, Task or Task<T> are required, but not async. This is shown in #ReedCopsey's answer and in the following correct example (slightly adapted from this useful SO answer):
public Task<int> MethodTaskAsync(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
That's why interface method signatures don't need, and can't have, the async keyword: an 'asynchronous' method per se, without regard to how it might be implemented, is just a method that returns a started (and, possibly, already finished) Task or Task<T>.
If async doesn't mark a method as asynchronous, what does it do? It's a way to write asynchronous methods more simply: once you have applied it to a method, you can use the await keyword to tell the compiler to correctly handle subsidiary asynchronous calls for you very simply (without it, you could try to handle subsidiary Tasks manually, using lots more code like that in the code block above, but to do so would be very complex and error prone).
So if you just want to return a do-nothing, already-completed task from an 'asynchronous' (i.e. Task-returning) method, you can and should do so synchronously(!), as in #ReedCopsey 's answers, using Task.CompletedTask or Task.FromResult(...).

Task.ContinueWith method requires task argument?

I have a class with two methods, Load() and Process(). I want to be able to run these individually as background tasks, or in sequence. I like the ContinueWith() syntax, but I'm not able to get it to work. I have to take a Task parameter on the method I continue with and cannot have a Task parameter on the initial method.
I would like to do it without lambda expressions, but am I stuck either using them, forcing a task parameter on one of the methods, or creating a third method LoadAndProcess()?
void Run()
{
// doesn't work, but I'd like to do it
//Task.Factory.StartNew(MethodNoArguments).ContinueWith(MethodNoArguments);
Console.WriteLine("ContinueWith");
Task.Factory.StartNew(MethodNoArguments).ContinueWith(MethodWithTaskArgument).Wait();
Console.WriteLine("Lambda");
Task.Factory.StartNew(() => { MethodNoArguments(); MethodNoArguments(); }).Wait();
Console.WriteLine("ContinueWith Lambda");
Task.Factory.StartNew(MethodNoArguments).ContinueWith(x => {
MethodNoArguments();
}).Wait();
}
void MethodNoArguments()
{
Console.WriteLine("MethodNoArguments()");
}
void MethodWithTaskArgument(Task t = null)
{
Console.WriteLine("MethodWithTaskArgument()");
}
In all overloads of ContinueWith(), the first parameter is a delegate that takes a Task, so you can't pass a parameterless delegate to it.
I think that using lambdas is perfectly fine and that it doesn't hurt readability. And the lambda in your code is unnecessarily verbose:
Task.Factory.StartNew(MethodNoArguments).ContinueWith(_ => MethodNoArguments())
Or, as Cory Carson pointed out in a comment, you could write an extension method:
public static Task ContinueWith(this Task task, Action action)
{
return task.ContinueWith(_ => action());
}
Writing clean code when you use multiple continuations is not that easy, although you can follow a few rules to make code cleaner:
Use the shorter form from svick's answer
Avoid chaining the continuations. Store the result of each continuation in a separate variable and then call ContinueWith in a separate line
If the continuation code is long, store it in a lambda variable and then ContinueWith the lambda.
Use an extension method like this "Then" method to make your code even cleaner.
You can change your code to something like this, which is slightly cleaner:
var call1=Task.Factory.StartNew(()=>MethodNoArguments());
var call2 = call1.ContinueWith(_ => MethodNoArguments());
call2.Wait();
or even
var call1 = Task.Factory.StartNew<Task>(MethodNoArguments);
var call2 = call1.Then(MethodNoArguments);
call2.Wait();
Stephen Toub discusses the Then extension and other ways you can clean up your code in Processing Sequences of Asynchronous Operations with Tasks
This problem is solved for good in C# 4. In C# 5 you can use the async/await keywords to create clean code that looks like the original synchronous version, eg:
static async Task Run()
{
await MethodNoArguments();
await MethodNoArguments();
}
static async Task MethodNoArguments()
{
await Task.Run(()=>Console.WriteLine("MethodNoArguments()"));
}
Visual Studio 11 and .NET 4.5 have a Go Live license so you could probably start using them right away.
You can use the Async CTP in C# 4 to achieve the same result. You can use the Async CTP in production as it has a go live license. The downside is that you 'll have to make some small changes to your code when you move to .NET 4.5 due to differences between the CTP and .NET 4.5 (eg. CTP has TaskEx.Run instead of Task.Run).

Categories

Resources