I have two asynchronous methods Task<int> DoInt() and Task<string> DoString(int value). I have a third asynchronous method Task<string> DoBoth(int value) whose goal is to asynchronously execute DoInt(), piping it’s output to DoString(int) and having the result be the result of DoBoth().
The important constraints are:
- I may not have source code to
DoInt()orDoString(), so I can’t
modify them. - I don’t want to block at any point
- Output (result) of one task must be passed as input to the next
- The final output (result) is what I want to be the result of
DoBoth()
The key being I already have methods that are asynchronous (i.e. return Task) and I want to pipe data from task to task, without blocking along the way, returning the final result in the initial task. I can do all the following except not blocking in the following code:
Code example:
// Two asynchronous methods from another library, i.e. can't be changed
Task<int> DoInt();
Task<string> DoString(int value);
Task<string> DoBoth()
{
return DoInt().ContinueWith<string>(intTask =>
{
// Don't want to block here on DoString().Result
return DoString(intTask.Result).Result;
});
}
Since Task<string> DoString(int) is already an asynchronous method, how do I cleanly create a non-blocking continuation to it? Effectively I want to create a continuation from an existing Task and not from a Func.
You can write the entire chain using TaskExtensions.Unwrap as:
Note that this assumes that
DoIntis defined asTask<int> DoInt(int value);, which differs from your description, but follows your code example.If DoInt does not take an int argument (matching your declarations), this could become:
As an extra – using C# 5 and .NET 4.5 (or the async targeting pack), you can write this as: