2

如果完成源被取消,我会在结果变量中收到什么?

async void SomeMethod()
{
   .....
   Run();
   var result = await GetResult();
   .....
}

Task<SomeResult> GetResult()
{
    return myCompletionSource.Task;
}

TaskCompletionSource myCompletionSource;

void Run()
{
     myCompletionSource= new TaskCompletionSource();
     TriggerSomeLongLastingLogicWhichWillCallCallBackBelow();

}

void SomeCallback()
{
     if (someCondition)
     {
         myCompletionSource.SetResult(<someResult>);
     }
     else
     {
         myCompletionSource.SetCancelled();
     }
}

我不太确定这种方法是否正确。

  1. 换句话说,依赖任务状态而不是为带有状态变量的“someresult”创建包装器是一种好习惯吗?
  2. 如何处理取消的任务?我不喜欢回调,也不喜欢使用 ContinueWith 的解决方案,我可以在其中分析任务状态。
4

1 回答 1

4

如果完成源被取消,我会在结果变量中收到什么?

您的代码将OperationCancelledException在等待取消的任务时抛出。所以结果变量永远不会被设置。

您可以使用块处理异常try/catch

async Task SomeMethod()
{
   try
   {
       .....
       Run();
       var result = await GetResult();
   }
   catch(OperationCancelledException)
   {
       // handle cancelled operation
   }
}

此外,SomeMethod应该返回 aTask因为void返回async方法通常只适用于事件处理程序,因为它们必须返回void我在这里简要介绍一下。

通常,如果您希望某个操作可取消,则传入一个CancellationToken操作必须检查的操作并将其传递给它启动的其他操作。所以你将它一路传递到你的回调中。

您还可以在CancellationToken取消TaskCompletionSource令牌时使用取消注册回调,因此您无需在方法中执行此操作。

void Run()
{   
     var cts = new CancellationTokenSource();
     var myCompletionSource= new TaskCompletionSource();
     cts.Token.Register(() => myCompletionSource.SetCancelled());

     TriggerSomeLongLastingLogicWhichWillCallCallBackBelow(cts.Token);         
}

void SomeCallback(CancellationToken token)
{       
     // do some work
     ....

     token.ThrowIfCancellationRequested();

     if (someCondition)
     {
         myCompletionSource.SetResult(<someResult>);
     }
     else
     {
         myCompletionSource.SetException(new Exception("error occcured"));
     }
}
于 2015-04-22T07:01:21.657 回答