I'm converting some async/await code to chained tasks, so I can use it in the released framework. The await code looks like this
public async Task<TraumMessage> Get() {
var message = await Invoke("GET");
var memorized = await message.Memorize();
return memorized;
}
where
Task<TraumMessage> Invoke(string verb) {}
Task<TraumMessage> Memorize() {}
I was hoping to chain Invoke
and Memorize
to return the task produced by Memorize
, but that results in a Task<Task<TraumMessage>
. The solution i've ended up is a TaskCompletionSource<TraumMessage>
as my signal:
public Task<TraumMessage> Get() {
var completion = new TaskCompletionSource<TraumMessage>();
Invoke("GET").ContinueWith( t1 => {
if(t1.IsFaulted) {
completion.SetException(t1.Exception);
return;
}
t1.Result.Memorize().ContinueWith( t2 => {
if(t2.IsFaulted) {
completion.SetException(t2.Exception);
return;
}
completion.SetResult(t2.Result);
});
});
return completion.Task;
}
Is there a way to accomplish this without the TaskCompletionSource
?
Run turns something synchronous into a Task (by running it on a separate thread), TaskCompletionSource turns something that is already asynchronous into a Task . "If it is already asynchronous, why does it need to be turned into a Task ?"
Is it safe to pass non-thread-safe objects created on one thread to another using TaskCompletionSource. SetResult()? Yes, as long as the object can be used on a different thread than the one it was created on (of course).
Task is more abstract then threads. It is always advised to use tasks instead of thread as it is created on the thread pool which has already system created threads to improve the performance. The task can return a result. There is no direct mechanism to return the result from a thread.
Task parallelism is the process of running tasks in parallel. Task parallelism divides tasks and allocates those tasks to separate threads for processing.
Yes, the framework comes with a handy Unwrap() extension method for exactly what you want.
Invoke("GET").ContinueWith( t => t.Result.Memorize() ).Unwrap();
If you're doing cancellation then you'll need to pass cancel tokens into the appropriate places, obviously.
I think that's pretty much the only way to accomplish what you want. Chaining disparate Tasks together isn't supported by the continuation APIs, so you have to resort to using a TaskCompletionSource
like you have to coordinate the work.
I don't have the Async CTP installed on this machine, but why don't you take a look at the code with a decompiler (or ILDASM if you know how to read IL) to see what it's doing. I bet it does something very similar to your TCS code under the covers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With