首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何检索ValueTask的异常?

如何检索ValueTask的异常?
EN

Stack Overflow用户
提问于 2018-10-22 17:30:58
回答 3查看 949关注 0票数 2

即将推出的C# 8 IAsyncEnumerable的设计使用ValueTaskValueTask<T>将可能同步的结果传回给使用者逻辑。它们都有IsFaulted属性,但与Task不同的是,它们没有Exception属性。

有没有可能有一个不持有正常Task并且处于故障或取消状态的ValueTask

ValueTask<T>.Result的文档表明,在失败的任务上调用它将重新抛出包含的Exception

代码语言:javascript
复制
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的使用在我的理解中是有问题的。

EN

回答 3

Stack Overflow用户

发布于 2018-10-22 21:24:18

阻塞直到TaskTask<T>完成的常见方法是调用Task.Wait() method

如果抛出一个异常,它将是一个System.AggregatedExceptionInnerExceptions property将拥有导致当前异常的异常集合。

从.NET Framework4.5和.NET Core1.0开始,还有GetAwaiter() method,您可以在其中对返回值调用GetResult(),并抛出集合中的第一个异常。

但是你永远不应该这样做!

您应该这样做:

代码语言:javascript
复制
// this has to work in a non-async method
try {
    var x = await valueTask;
} catch (Exception ex) {
    // work with the exception
}

当结果可能已经可用时,可以使用ValueTaskValueTask<T>来避免堆分配。这并不意味着阻止该任务是安全的。

票数 1
EN

Stack Overflow用户

发布于 2018-10-23 22:24:43

corefx team的回应表明,这确实不可能直接实现,并且由于需要更改配套接口而不能轻松添加,这将带来复杂的问题。

正如我最初猜测的那样,解决方法建议使用AsTask来获取Exception

代码语言:javascript
复制
IAsyncEnumerable<int> asyncSequence = ...

ValueTask<bool> valueTask = asyncSequence.MoveNextAsync();

if (valueTask.IsFaulted) {
    var ex = valueTask.AsTask().Exception;
    // work with the exception
}

ValueTask endTask = asyncSequence.DisposeAsync();

if (endTask.IsFaulted) {
    var ex = valueTask.AsTask().Exception;
    // work with the exception
}
票数 1
EN

Stack Overflow用户

发布于 2018-10-22 18:42:42

最好的办法是使用try语句,并尝试捕获那里的异常,然后再处理它……关于不包含普通任务的ValueTask,我认为您可以使用lambda方法来解决这个问题。

代码语言:javascript
复制
try {
    var x = Task.Run(()=>{ ... });
}
catch (Exception ex) {
    // Do something with exception.
}

或者无论ValueTask的情况是什么。考虑到C#在过去的构建中关注了很多异步任务,可以放心地说你会使用lambda和事件调用。

代码语言:javascript
复制
private void foo(ValueTask task) {
        lock (threadObj) {
            var x = Task.Run(()=> { return task.doWork(); }
            if (x == true) {
                // then do other work...
            }
            else {
                // handle 'exception'...
            }
        }
}
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52926184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档