【问题标题】:Task.wait and continueWIthTask.wait 和 continueWith
【发布时间】:2013-07-05 22:14:10
【问题描述】:

我有如下任务。

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,一切都会顺利进行。

【问题讨论】:

  • 对我来说听起来像是死锁,您是在单线程环境中执行此操作吗?我以前在 Windows Phone 开发中看到过这种情况。 (related)

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


【解决方案1】:

我强烈怀疑您的上下文是 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);

【讨论】:

  • 谢谢大家。Stephen 是的,它可以工作。不幸的是,我正在使用 vs2010,现在无法升级到 vs2012。有没有办法让 UI 线程等到任务并继续完成。跨度>
  • 您唯一的选择是在没有任务调度程序的情况下运行延续,或者将剩余的工作作为延续。是的,对于任何一种现实世界的异步场景,这都会很快变得非常混乱。这就是async 被发明的原因。
【解决方案2】:

好吧,如果不查看实际的异步操作是什么,就很难判断您的代码出了什么问题,我所知道的只是根据 MSDN waits for the task to be completed。是否有可能因为您正在尝试使用当前 SynchronizationContext 您的操作阻塞?

我问的原因是因为你

  1. 开始任务
  2. 等待任务完成(即继续任务)
  3. 任务尝试使用当前 SynchronizationContext 继续
  4. 任务尝试获取主线程
  5. 任务计划在等待完成后占用线程
  6. 但 Wait 正在等待当前任务完成(死锁)



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

【讨论】:

  • Charles 谢谢是的,我现在明白发生了死锁我需要 Task.wait 后继续的原因是让 UI 线程等待。有没有办法我可以使用主线程等到任务并继续完成。
【解决方案3】:

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

await Task.Delay(30000);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多