Reputation:
I recently learned about Task.ContinueWith and am trying to apply it to some existing code I have for better performance. I have something like this:
public static async Task<TResult> DoWork<T, TResult>(T value)
{
var fooResult = await Foo(value);
return await Bar<TResult>(fooResult);
}
private static Task<MyClass> Foo<T>(T value)
{
return GetMyClassFromValueAsync(value);
}
private static Task<TResult> Bar<TResult>(MyClass myClass)
{
return myClass.DoOperationAsync();
}
and was thinking I could improve it by doing something like this instead:
public static Task<TResult> DoWork<T, TResult>(T value)
{
return Foo(value).ContinueWith(fooResult => Bar<TResult>(fooResult.Result));
}
The problem that I'm running into is that ContinueWith returns a type of Task<Task<TResult>>
in this case because it wraps my async call in another task. The only solution I've found is to do something like this:
public static async Task<TResult> DoWork<T, TResult>(T value)
{
return await await Foo(value).ContinueWith(fooResult => Bar<TResult>(fooResult.Result));
}
but that just looks wrong and forces me to await it. Is there a better way to handle this situation?
There's also a lot happening behind the scenes with these calls, so if I'm taking the wrong approach or my intuition is leading me astray and I should stick with my original approach, please let me know why so I can learn and improve. Thanks!
Upvotes: 0
Views: 457
Reputation: 14856
Using ContinueWiht
can be problematic and it's unnecessarily complicated.
Just embrace async-await
:
public static async Task<TResult> DoWork<T, TResult>(T value)
{
return await Bar<TResult>(await Foo(value));
}
Upvotes: 1
Reputation: 6870
You are looking to chain together promises and return the final result, there is an extension method Unwrap
for this.
Example:
class Program
{
static void Main(string[] args)
{
var finalWork = Work().ContinueWith(work => MoreWork(work.Result)).Unwrap();
finalWork.Wait();
var finalWorkResult = finalWork.Result;
Console.WriteLine(finalWorkResult);
}
private static Task<string> MoreWork(string s)
{
return Task.FromResult($"{s} done... now more work.");
}
private static Task<string> Work()
{
return Task.FromResult("Work work");
}
}
Upvotes: 1
Reputation: 11474
You are very close. You are missing the UnWrap
method at the end.
public static async Task<TResult> DoWork<T, TResult>(T value)
{
return await await Foo(value).ContinueWith(fooResult => Bar<TResult>(fooResult.Result)).UnWrap();
}
In reality though, what you are doing with ContinueWith
is no more efficient than what you had before with the await
. I believe the await
is just syntactic sugar for ContinueWith
. I personally find await
much easier to read.
Upvotes: 1