C# 如何检索ValueTask的异常?
即将推出的C#8的设计使用C# 如何检索ValueTask的异常?,c#,async-await,task,C#,Async Await,Task,即将推出的C#8的设计使用ValueTask和ValueTask将潜在的同步结果传回消费者逻辑。它们都有IsFaulted属性,但与任务不同的是,没有异常属性 甚至可能有一个ValueTask无法保存正常的任务,并且处于故障或取消状态 ValueTask.Result的文档表明,在失败的任务上调用它将重新显示包含的异常。因此,以下代码提取异常是否有意义 IAsyncEnumerable asyncSequence=。。。 ValueTask ValueTask=asyncSequence.Mov
ValueTask
和ValueTask
将潜在的同步结果传回消费者逻辑。它们都有IsFaulted
属性,但与任务
不同的是,没有异常
属性
甚至可能有一个ValueTask
无法保存正常的任务,并且处于故障或取消状态
ValueTask.Result
的文档表明,在失败的任务上调用它将重新显示包含的异常。因此,以下代码提取异常是否有意义
IAsyncEnumerable asyncSequence=。。。
ValueTask ValueTask=asyncSequence.MoveNextAsync();
if(valueTask.IsFaulted){
//这必须在非异步方法中工作
//没有理由在此处阻止或使用
//异步关键字
试一试{
var x=valueTask.Result;
}捕获(例外情况除外){
//例外情况下工作
}
}
ValueTask endTask=asyncSequence.DisposeAsync();
if(endTask.IsFaulted){
//没有ValueTask.Result属性
//因此,上述方法不起作用
}
非通用的ValueTask
没有Result
属性。那么如何提取异常
一般来说,我认为应用AsTask
可以用于两种提取,但是,据我所知,我认为这会导致分配,使得ValueTask
的使用在一开始就有问题。你最好的选择是使用try语句,尝试捕获异常,然后稍后再处理它。。。
关于不包含正常任务的ValueTask,我认为您可以使用lambda方法来解决这个问题
try {
var x = Task.Run(()=>{ ... });
}
catch (Exception ex) {
// Do something with exception.
}
或者不管ValueTask的情况如何。考虑到C#在过去的构建中一直关注异步任务,可以肯定地说,您将使用lambda和事件调用
private void foo(ValueTask task) {
lock (threadObj) {
var x = Task.Run(()=> { return task.doWork(); }
if (x == true) {
// then do other work...
}
else {
// handle 'exception'...
}
}
}
在任务
或任务
完成之前进行阻止的常用方法是调用
如果抛出异常,它将是一个异常。将具有导致当前异常的异常集合
从.NET Framework 4.5和.NET Core 1.0开始,您还可以在其中对其返回值调用GetResult()
,并在集合中引发第一个异常
但你永远不应该这样做强>
您应该这样做:
// this has to work in a non-async method
try {
var x = await valueTask;
} catch (Exception ex) {
// work with the exception
}
ValueTask
和ValueTask
用于在结果可能已经可用时避免堆分配。这并不意味着阻止该任务是安全的。的响应表明这确实不可能直接实现,并且由于需要更改配套界面而无法轻松添加,这将带来复杂性
正如我最初猜测的那样,解决方案建议使用AsTask
获取异常
IAsyncEnumerable asyncSequence=。。。
ValueTask ValueTask=asyncSequence.MoveNextAsync();
if(valueTask.IsFaulted){
var ex=valueTask.AsTask().Exception;
//例外情况下工作
}
ValueTask endTask=asyncSequence.DisposeAsync();
if(endTask.IsFaulted){
var ex=valueTask.AsTask().Exception;
//例外情况下工作
}
这个答案对我来说毫无意义。首先,我有一个通过第三方方法返回给我的ValueTask
。另外,关于ValueTask
,您指的是什么“lambdas”和“事件调用”?很抱歉,我说得不太清楚。但本质上,lambda是封装在括号和括号中的方法。ie foo(对象发送方,EventArgs e)等于(s,e)=>{…},事件调用正在利用事件并调用它们。ie someEvent?.Invoke((s,e)=>{…})此示例使用lambads和事件调用调用调用方法作为参数。。。这种编程通常在System.Linq中使用。因此,我想说的是,一旦你有了valueTask,你就可以在线程安全的环境中使用它,这可以让你捕获程序所表达的不想要的动作。我的问题与lambdas或创建任务无关。我已经有一个ValueTask
来自我无法控制的地方,必须从中获取异常
。您使用.Result
而不是async
/wait
有什么原因吗?您确实知道(取决于您的上下文),这是基于您的注释的上述内容的可能重复这必须在非异步方法中工作这似乎是您的根本问题,但如果没有更多上下文,则很难判断是否存在异常无法从IValueTaskSource
,因此,从这里我看到了两种方法:要么.AsTask().Exception
要么.GetAwaiter().GetResult()
捕获异常。令人惊讶的是,AsTask()
实际上让底层的IValueTaskSource
抛出异常,捕获它,并从中创建一个错误的任务:起初我很困惑,没有一个更优化的路径,但最终异常的代价是如此高昂,以至于一旦你得到了一个异常,你就不应该再关心微优化了。发布它:首先,我必须使用ValueTask
,其中IsFaulted
istrue
,因此我不必为任何事情而阻塞。第二个似乎是分配的,因此我不太可能比使用AsTask
更好。第三,提取应该在没有wait
的情况下工作,因为父方法不是,也不能标记为async
。如果不能使用async
,请坚持使用IEnumerable
。可能我不清楚,但使用ValueTask
是必须的。我无法更改为IEnumerable
,因为它对我的情况没有语义意义,而且不可能,因为我尝试与之交互的API不是def