如何获取System.Threading.Tasks.Task已完成的通知

Ben*_*ams 36 .net c# .net-4.0

我目前正在使用.net 4中的新System.Threading.Tasks功能替换一些新的实现功能.

我有一个小问题,虽然我可以想到一些解决方案,我想要一些建议,通常是最好的方法,如果我在某处错过了一个技巧.

我需要的是一个任意进程能够启动一个任务,然后继续而不是等待任务完成.不是问题,但是当我需要对任务的结果做一些事情时,我不太确定这样做的最佳方式.

我见过的所有示例都在任务上使用Wait()直到它完成或在任务上引用Result参数.这两个都将阻止启动Task的线程,这是我不想要的.

我想到的一些解决方案:

  1. 创建一个新线程并在其上启动任务,然后使用Wait()或.Result阻塞新线程并以某种方式将结果同步回调用者,可能需要轮询任务IsCompleted参数.

  2. 有一个'Notify Completed'任务,我可以在完成我要运行的任务后启动,然后引发静态事件或其他事情.

  3. 将委托传递给任务的输入并调用该任务以通知任务已完成.

我可以为所有这些人思考或利弊,但我特别不喜欢在第一个使用Task类的目标之一时必须显式创建一个新线程来启动任务的想法.从直接线程使用中抽象出来.

关于最佳方式的任何想法?我错过了一些简单的事吗?"完成"事件会不会要求太多了:)?(当然有一个很好的理由没有一个!)

Jon*_*eet 39

怀疑你在寻找Task.ContinueWith(或Task<T>.ContinueWith).这些基本上说,"当你完成这个任务,执行这个动作." 但是,您可以指定各种选项以对其进行更多控制.

MSDN在"如何:使用连续性链接多个任务""继续任务"中详细介绍了这一点.

  • 对不起,你是完全正确的.我最初阅读MSDN上的所有内容,包括你发布的所有链接但由于某种原因,我读取Task.ContinueWith,在初始任务完成后将另一个Task作为执行参数,而不是简单的Action或Func.非常感谢,虽然我现在感到愚蠢:) (2认同)
  • @Ben Williams:别担心 - 它会让人很困惑:) (2认同)

Pet*_*iho 10

在现代C#中,不再需要ContinueWith()显式调用.原来的接受的答案另一种方法是简单地创建一个async该方法awaitS中的Task问题,并不会为所欲为的时候Task完成.

例如,假设您要TaskCompletedTask完成时引发一个被调用的事件.你会写一个像这样的方法:

async Task RaiseEventWhenTaskCompleted(Task task)
{
    await task;
    TaskCompleted?.Invoke(this, EventArgs.Empty);
}
Run Code Online (Sandbox Code Playgroud)

要"注册"等待,只需调用上面的方法.根据需要在上面的方法中添加异常处理,或者在最终将观察Task上述方法返回的代码中添加异常处理.

  • 这并不总是正确的!例如,这个 `await` 会阻塞 UI 线程,但是 `ContinueWith` 会在第一个线程之后执行而不阻塞当前的 UI (2认同)

Ste*_*ary 5

您可以应用任务继续

或者,Task实现IAsyncResult,因此您可以为该接口使用标准方法(阻塞,轮询或等待WaitHandle)。


小智 5

 Task task = Task.Run ( () => { Thread.Sleep ( 2000 ); } );

 task.GetAwaiter ().OnCompleted ( () => 
   {
     MessageBox.Show ( "the task completed in the main thread", "");
   } );
Run Code Online (Sandbox Code Playgroud)