一个很好的解决方案等待在try / catch /终于? [英] A good solution for await in try/catch/finally?

查看:160
本文介绍了一个很好的解决方案等待在try / catch /终于?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在 catch 块中调用 async 方法,然后再次抛出异常(使用其堆栈跟踪)这样:

  try 
{
//做某事
}
catch
{
//< - 用异步方法清理这些东西
throw;
}

但不幸的是,您不能使用 await catch finally block。我知道这是因为编译器没有办法回到 catch 块中执行你的等待之后的内容等待指令或类似的东西...



我尝试使用 Task.Wait()替换 await ,我有一个僵局。我在网上搜索了如何避免这种情况,并发现本网站



自从我不能更改 async 方法,也不知道他们是否使用 ConfigureAwait(false),我创建了这些方法采取 Func< Task> ,一旦我们处于不同的线程(以避免死锁)并等待完成,则启动异步方法:

  public static void AwaitTaskSync(Func< Task> action)
{
Task.Run(async()=> await action 。).ConfigureAwait(假))等待();
}

public static TResult AwaitTaskSync< TResult>(Func< Task< TResult>>动作)
{
返回Task.Run(async()=> ;等待action()。ConfigureAwait(false))。
}

public static void AwaitSync(Func< IAsyncAction> action)
{
AwaitTaskSync(()=> action()AsTask());
}

public static TResult AwaitSync< TResult>(Func< IAsyncOperation< TResult>>动作)
{
return AwaitTaskSync(()=> action ).AsTask());
}

所以我的问题是:你认为这段代码好吗? >

当然,如果你有一些增强或者知道一个更好的方法,我在听! :)

解决方案

您可以将逻辑移至 catch 如果需要,可以使用 ExceptionDispatchInfo

  static async任务f()
{
ExceptionDispatchInfo takenException = null;
try
{
等待TaskThatFails();
}
catch(MyException ex)
{
snapsException = ExceptionDispatchInfo.Capture(ex);
}

if(snapsException!= null)
{
等待ExceptionHandler();

snapsException.Throw();
}
}

这样,当调用者检查异常的 StackTrace 属性,它仍然记录在$ code> TaskThatFails 之内的地方。


I need to call an async method in a catch block before throwing again the exception (with its stack trace) like this :

try
{
    // Do something
}
catch
{
    // <- Clean things here with async methods
    throw;
}

But unfortunately you can't use await in a catch or finally block. I learned it's because the compiler doesn't have any way to go back in a catch block to execute what is after your await instruction or something like that...

I tried to use Task.Wait() to replace await and I got a deadlock. I searched on the Web how I could avoid this and found this site.

Since I can't change the async methods nor do I know if they use ConfigureAwait(false), I created these methods which take a Func<Task> that starts an async method once we are on a different thread (to avoid a deadlock) and waits for its completion:

public static void AwaitTaskSync(Func<Task> action)
{
    Task.Run(async () => await action().ConfigureAwait(false)).Wait();
}

public static TResult AwaitTaskSync<TResult>(Func<Task<TResult>> action)
{
    return Task.Run(async () => await action().ConfigureAwait(false)).Result;
}

public static void AwaitSync(Func<IAsyncAction> action)
{
    AwaitTaskSync(() => action().AsTask());
}

public static TResult AwaitSync<TResult>(Func<IAsyncOperation<TResult>> action)
{
    return AwaitTaskSync(() => action().AsTask());
}

So my questions is: Do you think this code is okay?

Of course, if you have some enhancements or know a better approach, I'm listening! :)

解决方案

You can move the logic outside of the catch block and rethrow the exception after, if needed, by using ExceptionDispatchInfo.

static async Task f()
{
    ExceptionDispatchInfo capturedException = null;
    try
    {
        await TaskThatFails();
    }
    catch (MyException ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }

    if (capturedException != null)
    {
        await ExceptionHandler();

        capturedException.Throw();
    }
}

This way, when the caller inspects the exception's StackTrace property, it still records where inside TaskThatFails it was thrown.

这篇关于一个很好的解决方案等待在try / catch /终于?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆