Task.ContinueWith method requires task argument? - c#

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).

Related

What is the proper way to await for async inside of a ForEach?

.NET Core 2.2, VS 2019
The problem is, the UpdateDatabaseWithFile is never getting executed? What am I doing wrong here? I tried to wrap Directory with an await, but I can't, since it returns void. What is the proper way to do this?
Here is the code:
Directory
.GetFiles(#"C:\Temp")
.ToList()
.ForEach(async file =>
{
await this._dataService.UpdateDatabaseWithFile();
});
It is because ForEach<T> just executes that async functions, but didn't wait for their completion.
You can use Select for projecting Tasks which has to be executed and then use Task.WhenAll() to execute that functions and wait for their completion:
var tasks = Directory
.GetFiles(#"C:\Temp")
.Select(async file =>
{
await this._dataService.UpdateDatabaseWithFile();
});
await Task.WhenAll(tasks);
Or if you want to execute functions sequentally, then instead of Task.WhenAll() you can use simple foreach:
foreach (var file in Directory.GetFiles(#"C:\Temp"))
{
await this._dataService.UpdateDatabaseWithFile();
}
Additional explanation:
Here is the implementation of ForEach<T>:
for(int i = 0 ; i < array.Length; i++) {
action(array[i]);
}
As you see it just executes that action but didn't wait for their completion. And actually, it can't. Action returns nothing. But for waiting Task has to be returned. So, for making ForEach function useful in that situation, it has to take Func which return Task and then await inside for iterator..
The method List.ForEach doesn't understand async delegates, in other words it hasn't an overload that accepts a Func<Task<T>> parameter. In these cases what happens is that the supplied async lambda is treated as async void. Async voids are evil, because they can't be awaited, so their execution can't be coordinated with other parts of the program. They are similar to fire-and-forget tasks, with the added drawback of killing the process in case of an exception.
Void-returning async methods have a specific purpose: to make asynchronous event handlers possible.
You should pay attention to the signature of the method you are attempting to call with an async delegate as argument. Some methods like Task.Run have specific overloads for async delegates, and handle them well. Other methods like the LINQ Select are not designed with async await in mind, but at least they accept arguments of type Func instead of Action, and so the generated tasks are returned and can be collected and awaited properly. Methods like the List.ForEach with Action arguments should never be used with async delegates.
The most likely problem here is that .ForEach() provides no way for you to actually wait for the operations to complete. It will just execute them and move on.
Eric Lippert has a good blog post on why the .ForEach() method isn't all that great, and this is a perfect example of how a foreach loop excels over .ForEach - foreach will allow you to actually await the operations.
Just use a loop, and your problems go away:
foreach (var file = Directory.GetFiles(#"C:\Temp"))
{
await this._dataService.UpdateDatabaseWithFile();
}
It should be noted that you don't seem to actually be using the file variable anywhere, and that seems like a problem. Hopefully just a typo?

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(...).

Should I omit async / await if possible?

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.

Categories

Resources