这在一定程度上取决于您希望何时引发错误 - 即急切地提出错误,或者作为等待的一部分。与迭代器块一样,如果您想要急切的错误检查,则需要两种方法,例如:
public Task<int> SomeMethod(..args..) {
if(..args fail..) throw new InvalidOperationException(...);
return SomeMethodImpl(...args...);
}
private async Task<int> SomeMethodImpl(...args...)
{
... await etc ...
}
然后,这将执行任何参数检查作为初始调用的一部分,而不是等待。如果您希望异常成为可等待的一部分,则可以将其抛出:
public async Task<int> SomeMethod(..args..) {
if(..args fail..) throw new InvalidOperationException(...);
... await etc ...
}
但是,在您的示例中,您正在使用 a 的事实return
表明Task
这实际上不是一种async
方法,而是一种异步(但不是async
)方法。你不能这样做:
return new Task(() => { throw new ArgumentNullException("argument"); });
因为那Task
永远不会开始——而且永远不会。我怀疑您需要执行以下操作:
try {
throw new InvalidArgumentException(...); // need to throw to get stacktrace
} catch(Exception ex) {
var source = new TaskCompletionSource<int>();
source.SetException(ex);
return source.Task;
}
这是……有点拗口,可能封装得更好一点。这将返回一个Task
表明它处于Faulted
状态的。