如果完成源被取消,我会在结果变量中收到什么?
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();
}
}
我不太确定这种方法是否正确。
答案 0 :(得分:4)
如果完成源被取消,我会在结果变量中收到什么?
在等待已取消的任务时,您的代码将抛出OperationCancelledException
。所以结果变量永远不会被设置。
您可以使用try/catch
块处理异常:
async Task SomeMethod()
{
try
{
.....
Run();
var result = await GetResult();
}
catch(OperationCancelledException)
{
// handle cancelled operation
}
}
此外,SomeMethod
应该返回Task
,void
返回async
方法通常仅适用于事件处理程序,因为它们必须返回void
。我在博客中简要介绍here。
一般情况下,如果您希望操作可取消,则传入操作必须检查的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"));
}
}