问题描述
我需要重新抛出异常(与它的堆栈跟踪之前调用一个异步
方法在抓
块)是这样的:
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;
}
但不幸的是你不能使用等待
在抓
或最后
块。我了解到这是因为编译器没有任何办法回去了抓
块来执行你是什么的await $ C $之后C>指令或类似的东西...
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...
我试图用 Task.Wait()
来代替等待
,我得到了一个僵局。我搜索在网络上我怎么能避免这种情况,发现this网站。
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.
既然不能改变异步
方法,我也不知道,如果他们使用 ConfigureAwait(假)
,我创建了这些方法,它采取了 Func键&LT;任务&GT;
启动异步方法,一旦我们在不同的线程(以避免死锁),并为其完成等待:
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());
}
所以我的问题是:你认为这个code是好
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! :)
推荐答案
您可以将逻辑抓
块外后重新抛出异常,如果需要的话,由使用<$c$c>ExceptionDispatchInfo$c$c>.
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();
}
}
这样,当主叫检查异常的堆栈跟踪
属性,在 TaskThatFails
它仍然记录在那里被扔
This way, when the caller inspects the exception's StackTrace
property, it still records where inside TaskThatFails
it was thrown.
这篇关于在try / catch语句进行的await一个好的解决方案/最后?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!