Bug in TPL - TaskContinuationOptions.ExecuteSynchronously?
.net, task, task-parallel-library
Solution
Filed a bug on connect on your behalf - hope that's ok :)
https://connect.microsoft.com/VisualStudio/feedback/details/744326/tpl-wait-call-on-task-doesnt-return-until-all-continuations-scheduled-with-executesynchronously-also-complete
I agree that it's a bug, just wanted to post a code snippet that shows the issue without having an 'endless' wait. The bug is that an ExecuteSynchronously means Wait calls on the first task don't return until the ExecuteSynchronously continuations are also completed.
Running the below snippet shows it waits 17 seconds (so all 3 had to complete instead of just the first one). It's the same whether the third task is scheduled off the first or the second (so this ExecuteSynchronously will continue through the tree of tasks scheduled as such).
void Main()
{
var task = new Task(() => Thread.Sleep(2 * 1000));
var secondTask = task.ContinueWith(
_ => Thread.Sleep(5 * 1000),
TaskContinuationOptions.ExecuteSynchronously);
var thirdTask = secondTask.ContinueWith(
_ => Thread.Sleep(10 * 1000),
TaskContinuationOptions.ExecuteSynchronously);
var stopwatch = Stopwatch.StartNew();
task.Start(TaskScheduler.Default);
task.Wait();
Console.WriteLine ("Wait returned after {0} seconds", stopwatch.ElapsedMilliseconds / 1000.0);
}
The only thing that makes me think it might be intentional (and therefore more a doc bug than code bug) is Stephen's comment in this blog post:
ExecuteSynchronously is a request for an optimization to run the continuation task on the same thread that completed the antecedent task off of which we continued, in effect running the continuation as part of the antecedent’s transition to a final state
Problem
I think I spotted a serious bug in TPL. I am not sure. I spent a lot of time scratching my head and cannot understand the behavior. Can anyone help? What my scenario is: - I create a task that does simple thing. No exceptions etc. - I register a continuation with ExecuteSynchronously set. It must be on the same thread. - I start the task on default taskscheduler (ThreadPool). The starting thread proceeds and waits for it. - The task starts. Passes. - The continuation starts on the same thread as task (making previous task completed!) and enters endless loop. - Nothing happens with waiting thread. Does not want to go further. Stuck on wait. I checked in debugger, task is RunToCompletion. Here is my code. Appreciate any help! ``` // note: using new Task() and then Start() to avoid race condition dangerous // with TaskContinuationOptions.ExecuteSynchronously flag set on continuation. var task = new Task(() => { /* just return */ }); task.ContinueWith( _task => { while (true) { } /* never return */ }, TaskContinuationOptions.ExecuteSynchronously); task.Start(TaskScheduler.Default); task.Wait(); // a thread hangs here forever even when EnterEndlessLoop is already called. ```