A surprise TaskCancelledException
All of a sudden, my code started getting a lot of TaskCancelledException. It took me a while to figure out what was going on. We can imagine that the code looked like this:
var unwrap = Task.Factory.StartNew(() =>
{
if (DateTime.Now.Month % 2 != 0)
return null;
return Task.Factory.StartNew(() => Console.WriteLine("Test"));
}).Unwrap();
unwrap.Wait();
The key here is that when Unwrap is getting a null task, it will throw a TaskCancelledException, which was utterly confusing to me. It make sense, because if the task is null there isn’t anything that the Unwrap method can do about it. Although I do wish it would throw something like ArgumentNullException with a better error message.
The correct way to write this code is to have:
var unwrap = Task.Factory.StartNew(() =>
{
if (DateTime.Now.Month % 2 != 0)
{
var taskCompletionSource = new TaskCompletionSource<object>();
taskCompletionSource.SetResult(null);
return taskCompletionSource.Task;
}
return Task.Factory.StartNew(() => Console.WriteLine("Test"));
}).Unwrap();
unwrap.Wait();
Although I do wish that there was an easier way to create a completed task.

Comments
The Async CTP has a static TaskEx.FromResult method that does exactly what you do:
public static Task FromResult(TResult result)
{
TaskCompletionSource source = new TaskCompletionSource(result);
source.TrySetResult(result);
return source.Task;
}
Expect this TaskEx class to be merged with the Task class for .Net 5.
3 lines of code that can be extracted into some static property hardly counts as a difficult way to create a completed task ;)
Oren,
have you gotten in Rx yet (as in fully grokked it)?
You seem to use tasks a lot. I myself use Rx for most of my asynchronous needs. It is usually a better concept. And regarding this case, it has Observable.Empty or Observable.Return(null) helpers which could your case, had you been using Rx.
Omer,
I would love to see some real examples of TPL vs. RX code, because I haven't really been able to figure out that.
And I think that with C# 5.0, TPL is a better alternative
This is from SO: http://stackoverflow.com/questions/2542764/tpl-v-s-reactive-framework
In general, tasks abstract single (future) values/computations and observables abstract streams of (future) values/computations. You could treat the single value case as a special case of a single value stream, and only use Rx. However if your use case primarily deals with single values, TPL might be a better feat.
Also, Rx allows for much better composition (using LINQ).
From my experience, Rx works best when replacing events.
For me - Rx was a mind enhancing experience, which changed the way I perceive many problems. I advise you to take a leap of faith here, and invest some time in this ingenious framework.
Omer,
Most of what we are doing are actually do computation of a single value.
For example, take a look at the type of things we do here:
public Task<BatchResult[]> BatchAsync(ICommandData[] commandDatas)
{
var metadata = new RavenJObject();
AddTransactionInformation(metadata);
var req = jsonRequestFactory.CreateHttpJsonRequest(this, url + "/bulk_docs", "POST", metadata, credentials, convention);
var jArray = new RavenJArray(commandDatas.Select(x => x.ToJson()));
var data = jArray.ToString(Formatting.None);
}
can you should me how this would be written, Rx style?
I'll give it a shot later.
I guess the basic idea would be to treat it as a stream of command batches, and project it (select) into a stream of responses. Along the way we could push the handling into a dedicated thread, or use the thread/task pool. we might also easily "batch our batches" based on count or time if that could increase our performance. we might also throttle against overloading / DoS attacks for example.
I cross-posted your example in the Rx forums, for help getting an expert opinion on this (http://social.msdn.microsoft.com/Forums/en/rx/thread/3cd72a7e-fba8-4c81-9113-36ef78e2ac54).
Omer,
None of those things are actually needed or required.
BatchAsync is being called from SaveChangesAsync, and there is usually only ever to be one of them.
Comment preview