在 try/catch/finally 中等待的一个好的解决方案? [英] A good solution for await in try/catch/finally?
问题描述
我需要在 catch
块中调用一个 async
方法,然后再像这样抛出异常(及其堆栈跟踪):
试试{//做一点事}抓住{//<- 用异步方法清理这里的东西扔;}
但不幸的是,您不能在 catch
或 finally
块中使用 await
.我了解到这是因为编译器没有任何方法可以返回 catch
块来执行 await
指令或类似指令之后的内容......>
我尝试使用 Task.Wait()
替换 await
并且我遇到了死锁.我在网上搜索如何避免这种情况,发现 本网站.
由于我无法更改 async
方法,也不知道它们是否使用 ConfigureAwait(false)
,因此我创建了这些采用 Func<;一旦我们在不同的线程上(以避免死锁)并等待它的完成,Task>
就会启动一个异步方法:
public static void AwaitTaskSync(Func action){Task.Run(async () => await action().ConfigureAwait(false)).Wait();}public static TResult AwaitTaskSync(Func>动作){return Task.Run(async () => await action().ConfigureAwait(false)).Result;}public static void AwaitSync(Func action){AwaitTaskSync(() => action().AsTask());}public static TResult AwaitSync(Func>动作){return AwaitTaskSync(() => action().AsTask());}
所以我的问题是:你认为这段代码好吗?
当然,如果您有一些改进或知道更好的方法,我会倾听!:)
您可以将逻辑移到 catch
块之外,并在需要时使用 ExceptionDispatchInfo
.
静态异步任务 f(){ExceptionDispatchInfo captureException = null;尝试{等待 TaskThatFails();}捕获(MyException 前){captureException = ExceptionDispatchInfo.Capture(ex);}如果(捕获异常!= null){等待异常处理程序();捕获异常.抛出();}}
这样,当调用者检查异常的 StackTrace
属性时,它仍会记录它在 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/finally 中等待的一个好的解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!