【发布时间】:2016-07-06 08:51:10
【问题描述】:
我有一个注册后台任务的方法,如下所示:
//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 错误。 Register() 方法永远不会在内部完成。实际上,10 秒后,token.ThrowIfCancellationRequested() 方法被调用,但它不会抛出到调用它的 try-catch 语句。最初我在没有 Task.Run() 的情况下直接调用 builder.Register() 但它不起作用,这也不起作用。
但是,如果我将btr = Task.Run(() =>... 替换为Task.Delay(ms),而ms > 10000,我的预期效果就会发生。
我做错了吗?还是有更好的方法来做到这一点?基本上我只需要在 builder.Register() 几秒钟后没有完成时使 registerTask() 方法返回 null 的代码。
【问题讨论】:
-
使用
.Result是有问题的,因为这会阻塞线程;你可以使用异步函数和await来代替吗? -
@Jacob 也许这就是正在发生的事情?我是从 Windows 运行时项目中执行此操作的,因此我无法使我的任务异步,我的编译错误说我应该将类型“任务”更改为 IAsyncAction 或其他内容,但我还没有真正做到这一点
标签: c# win-universal-app task cancellation cancellationtokensource