Task.wait和continueWIth

时间:2013-07-05 13:42:55

标签: c#-4.0 task-parallel-library

我正在完成如下任务。

var task = Task<string>.Factory.StartNew(() => longrunningmethod()
    .ContinueWith(a =>
             longrunningmethodcompleted((Task<string>)a,
                  TaskScheduler.FromCurrentSynchronizationContext())));

task.Wait();

我的任务将调用longrunning方法,完成后将调用完成的方法。 在我的长期运动方法中,我推迟Thread.Sleep(30000)。当我使用Task.wait系统挂起并且它没有调用longrunningmethodcompleted方法时。如果我不使用Task.wait,一切都很顺利。

3 个答案:

答案 0 :(得分:12)

我强烈怀疑您的上下文是UI上下文。

在这种情况下,您导致死锁,因为您告诉longrunningmethodcompleted在当前SynchronizationContext上执行。

然后,您通过调用Wait来阻止该上下文。延续将永远不会完成,因为它需要在Wait中阻止的线程上执行。

要解决此问题,您无法在该上下文中继续运行Wait。我假设longrunningmethodcompleted 必须在UI线程上运行,因此解决方案是通过调用Wait替换对ContinueWith的调用:

var ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task<string>.Factory.StartNew(() => longrunningmethod()
    .ContinueWith(a =>
         longrunningmethodcompleted((Task<string>)a,
         ui);
task.ContinueWith(..., ui);

或者,您可以升级到VS2012并使用async / await,这样可以编写更清晰的代码:

var task = Task.Run(() => longrunningmethod());
await task;
longrunningmethodcompleted(task);

答案 1 :(得分:0)

如果没有看到实际的异步操作是什么,很难说你的代码有什么问题,我所知道的只是根据MSDN waits for the task to be completed。是否有可能因为您尝试使用当前的SynchronizationContext操作阻止?

我问的原因是因为你

  1. 启动任务
  2. 等待任务完成(这是继续执行任务)
  3. 任务尝试继续使用当前的SynchronizationContext
  4. 任务尝试获取主线程
  5. 任务计划在等待完成后获取线程
  6. 但是等待当前任务完成(死锁)
  7. < /醇>



    我的意思是你的程序与Thread.Sleep(seconds)一起使用的原因是因为在时间限制结束后,线程将继续。

答案 2 :(得分:-1)

Thread.Sleep(nnn)正在阻止。使用Task.Delay(nnn)并等待:

await Task.Delay(30000);

编辑添加:刚刚注意到标签是C#4。这需要C#5和新的异步等待支持。说真的,如果你正在做异步和任务,你需要升级。