首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异常处理异步编程

异常处理异步编程
EN

Stack Overflow用户
提问于 2018-03-01 08:30:23
回答 1查看 375关注 0票数 0

我这里有一些密码。这是实类的简化版本:

代码语言:javascript
复制
public class Delayer
{
    //it has to be unawaitable
    public async void Execute(Action action)
    {
        await Task.Delay(10).ConfigureAwait(false);
        action.BeginInvoke(null, null); //action.Invoke();
    }
}

我用它:

代码语言:javascript
复制
private static Task TestFoo()
{
    throw new Exception();
}


delayer.Execute(async () =>
{
    //do something else
    await TestFoo().ConfigureAwait(false);
});

我不能通过将Execute方法传递到try/catch来实现这个异常,也不能通过将action.BeginInvoke(null, null)传递到try/catch来实现。如果在将异步lambda传递给Execute方法时使用try/catch包围它,我就可以处理它。

我的问题是:为什么异步lambda执行与等待?因为如果没有等待执行,异常就会被吞没。

我希望Execute方法吞下从操作中抛出的所有异常。有什么办法吗?我做错什么了?

加法:

Execute的行为必须是“只是一场火灾而忘记了行动”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-01 08:42:10

编辑

如果您真的非常想要一个Fire并忘记方法,那么唯一要做的就是捕获Execute方法中的所有异常。但是,如果您希望能够捕获异常,而不是在不可访问的BeginInvoke上使用Action,则必须接受可访问的任务。

代码语言:javascript
复制
public class Delayer
{
    public async Task Execute(Func<Task> action) // or public async void Execute(Func<Task> action) if you insist on it.
    {
        try
        {
            await Task.Delay(10).ConfigureAwait(false);
            await action.Invoke();
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
}

然后你就可以安全地做了

代码语言:javascript
复制
void CallDelayedMethod()
{
    var delayer = new Delayer();

    delayer.Execute(ThrowException);
}

public Task ThrowException()
{
    throw new Exception();  
}

我仍然会返回一个任务,并让调用者忽略它,不等待它(火和忘记)或不。

原始答案

您没有通过在类Delayer中使用异步无效签名来遵循最佳实践。

public async void Execute(Action action)

应该是

public async Task Execute(Action action)

因此,您可以等待对Execute的调用。否则,这只是一场火灾和遗忘操作,这使得捕捉异常变得困难。通过让它成为一种服务,你可以做到:

代码语言:javascript
复制
try
{
    await Delayer.Execute(...);
}
catch(Exception ex)
{
    ....
}

来自最佳做法

异步空方法有不同的错误处理语义。当异常从异步任务或异步任务方法中抛出时,该异常将被捕获并放置在Task对象上。有了异步空方法,就没有任务对象,所以从异步空方法中抛出的任何异常都将直接在异步空方法启动时处于活动状态的SynchronizationContext上引发。

此外,如果要向任务传递可接受的操作,则应该执行“接受任务”:

代码语言:javascript
复制
public async Task Execute(Func<Task> action)
{
    await Task.Delay(10).ConfigureAwait(false);
    await action.Invoke();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49045518

复制
相关文章

相似问题

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