7

我有一个像下面这样的任务。

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

task.Wait();

我的任务将调用 longrunning 方法,完成后将调用已完成的方法。在我的 longrunningmethod 中,我延迟了Thread.Sleep(30000). 当我使用 Task.wait 系统挂起并且它没有调用 longrunningmethodcompleted 方法。如果我不使用 Task.wait 一切都很好。

4

3 回答 3

13

我强烈怀疑您的上下文是 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);
于 2013-07-05T13:52:52.793 回答
0

好吧,如果没有看到实际的异步操作是什么,很难说出您的代码有什么问题,我所知道的只是根据 MSDN等待任务完成。是否有可能因为您正在尝试使用当前 SynchronizationContext 您的操作阻塞?

我问的原因是因为你

  1. 开始任务
  2. 等待任务完成(这是继续任务)
  3. 任务尝试继续当前的 SynchronizationContext
  4. 任务尝试获取主线程
  5. 等待完成后调度的任务走线程
  6. 但是等待正在等待当前任务完成(死锁)



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

于 2013-07-05T13:54:57.563 回答
-1

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

await Task.Delay(30000);

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

于 2013-07-05T13:48:19.783 回答