【发布时间】:2018-10-22 09:30:58
【问题描述】:
即将推出的 C# 8 IAsyncEnumerable 的设计使用 ValueTask 和 ValueTask<T> 将潜在的同步结果传达回消费者逻辑。它们都具有IsFaulted 属性,但与Task 不同的是,它们没有Exception 属性。
甚至可能有一个ValueTask 不包含正常的Task 并且处于故障或取消状态?
ValueTask<T>.Result 的文档表明在失败的任务上调用它会重新抛出包含的Exception。因此,以下代码对提取 Exception 有意义吗?
IAsyncEnumerable<int> asyncSequence = ...
ValueTask<bool> valueTask = asyncSequence.MoveNextAsync();
if (valueTask.IsFaulted) {
// this has to work in a non-async method
// there is no reason to block here or use the
// async keyword
try {
var x = valueTask.Result;
} catch (Exception ex) {
// work with the exception
}
}
ValueTask endTask = asyncSequence.DisposeAsync();
if (endTask.IsFaulted) {
// there is no ValueTask.Result property
// so the appoach above can't work
}
非泛型 ValueTask 没有 Result 属性。那么如何提取Exception呢?
一般来说,我认为应用AsTask 可以用于两种提取,但是,我认为它会导致分配,首先我理解ValueTask 的使用是有问题的。
【问题讨论】:
-
你使用
.Result而不是async/await有什么原因吗?你知道(取决于你的上下文)这个can deadlock? -
以上内容基于您的评论
this has to work in a non-async method这似乎是您的根本问题,但如果没有更多上下文就很难判断 -
没有办法从
IValueTaskSource检索异常,所以从那里我看到了两种方法:.AsTask().Exception或.GetAwaiter().GetResult()并捕获异常。令人惊讶的是,AsTask()居然让底层的IValueTaskSource抛出异常,捕获它,并从中创建一个故障任务:source.dot.net/#System.Private.CoreLib/shared/System/Threading/… 起初我很困惑,没有更优化的路径,但最终异常成本如此之高,以至于一旦你得到一个,你就不应该再关心微优化了
标签: c# async-await task