取消整个任务时,一个名为方法不返回

问题描述:

我有注册一个后台任务,看起来像这样的方法:取消整个任务时,一个名为方法不返回

//snippet from task builder method 
     try 
     { 
      cancellationTokenSource.CancelAfter(10000); 
      btr = Task.Run(() => registerTask(builder, btr,cancellationTokenSource.Token), cancellationTokenSource.Token).Result; 
     } 
     catch (OperationCanceledException) // something went wrong 
     { 
      return null; 
     } 



private BackgroundTaskRegistration registerTask(BackgroundTaskBuilder builder, BackgroundTaskRegistration btr, CancellationToken token) 
{ 
    CancellationTokenSource newToken = new CancellationTokenSource(); 
    Task cancelledCheck = Task.Run(() => 
    { 
     while (true) 
     { 
      if (token.IsCancellationRequested) 
      { 
       newToken.Cancel(); 
       token.ThrowIfCancellationRequested(); 
      } 
     } 
    }, newToken.Token); 
    btr = Task.Run(()=> builder.Register(),token).Result; 
    return btr; 
} 

我的问题是,有时builder.Register()方法不返回任何东西。这可能是某种Windows的bug; Register()方法永远不会在内部完成。事实上,在10秒钟后,token.ThrowIfCancellationRequested()方法被调用,但它不会抛出try-catch语句来调用它。最初我直接调用builder.Register()而没有Task.Run(),但它没有工作,也没有。

但是,如果我将btr = Task.Run(() =>...替换为Task.Delay(ms)而不是ms > 10000,我的预期效果就会发生。

我做错了什么?还是有更好的方法来做到这一点?基本上我只需要代码,这会使builder.Register()在几秒钟后没有完成时使registerTask()方法返回null。

+0

使用'.Result'会产生问题,因为这会阻塞线程;你可以使用异步函数和'await'来代替吗? – Jacob

+0

@Jacob也许这就是发生了什么?我是从Windows运行时项目做到这一点,所以我不能让我的任务异步,我的编译错误说像我应该改变类型“任务”IAsyncAction或类似的东西,但我还没有真正做到这一点 – Tyress

像这样的东西更换代码为我工作:

btr = null; 
    cancellationTokenSource.CancelAfter(10000); 
    Task registerTask = Task.Factory.StartNew(() => 
    { 
     btr = builder.Register(); 
    }); 
    Task cancellationTask = Task.Factory.StartNew(() => 
    { 
    while (true) 
    { 
     if (cancellationTokenSource.Token.IsCancellationRequested) break; 
    } 
    }, cancellationTokenSource.Token); 
    Task[] tasks = new Task[2] { cancellationTask, registerTask }; 
    Task.WaitAny(tasks); 

,而不是处理错误,得到一个取消请求将触发的任务结束之一,它结束时,我返回作业注册变量是否为空。