TPL中的错误 - TaskContinuationOptions.ExecuteSynchronously?

Sła*_*cki 8 .net task task-parallel-library

我想我在TPL中发现了一个严重的错误.我不确定.我花了很多时间挠挠脑袋,无法理解这种行为.有人可以帮忙吗?

我的情景是:

  1. 我创建了一个简单的任务.没有例外等
  2. 我用ExecuteSynchronously set注册了一个延续.它必须在同一个线程上.
  3. 我在默认的taskcheduler(ThreadPool)上启动任务.起始线程继续并等待它.
  4. 任务开始了.通行证.
  5. 继续从与任务相同的线程开始(使前一个任务完成!)并进入无限循环.
  6. 等待线程没有任何反应.不想再往前走.坚持等待.我在调试器中检查过,任务是RunToCompletion.

这是我的代码.感谢任何帮助!

// 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. 
Run Code Online (Sandbox Code Playgroud)

Jam*_*ing 5

代表您提交连接错误 - 希望没关系:)

https://connect.microsoft.com/VisualStudio/feedback/details/744326/tpl-wait-call-on-task-doesnt-return-until-all-continuations-scheduled-with-executesynchronously-also-complete

我同意这是一个错误,只是想发布一个代码片段,显示问题而没有"无休止"的等待.错误是ExecuteSynchronously意味着在完成ExecuteSynchronously延续之前,第一个任务上的Wait调用不会返回.

运行以下代码段显示它等待17秒(因此所有3个必须完成而不是仅完成第一个).无论第三个任务是在第一个任务还是第二个任务计划之后都是相同的(因此,这个ExecuteSynchronously将继续通过这样安排的任务树).

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);
}
Run Code Online (Sandbox Code Playgroud)

唯一让我觉得它可能是故意的(因此更多的是文档错误而不是代码错误)是斯蒂芬在这篇博文中的评论:

ExecuteSynchronously是一个优化请求,用于在完成我们继续的前一个任务的同一个线程上运行continuation任务,实际上是作为前一个过渡到最终状态的一部分运行continuation