use*_*050 89 .net c# exception-handling async-await c#-5.0
我需要async在catch块中调用一个方法,然后再次抛出异常(带有它的堆栈跟踪),如下所示:
try
{
// Do something
}
catch
{
// <- Clean things here with async methods
throw;
}
Run Code Online (Sandbox Code Playgroud)
但不幸的是你无法await在一个catch或一个finally块中使用.我学会了它是因为编译器没有任何方法可以回到catch块中来执行你的await指令之类的东西......
我试图用来Task.Wait()替换await,我遇到了僵局.我在网上搜索了如何避免这种情况并找到了这个网站.
由于我无法更改async方法,也不知道它们是否使用ConfigureAwait(false),因此我创建了这些方法,这些方法Func<Task>在我们处于不同的线程(以避免死锁)并等待其完成时启动异步方法:
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());
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:你觉得这段代码还可以吗?
当然,如果你有一些改进或知道更好的方法,我正在听!:)
小智 169
您可以在catch块之外移动逻辑,并在需要时使用重新抛出异常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();
}
}
Run Code Online (Sandbox Code Playgroud)
这样,当调用者检查异常的StackTrace属性时,它仍会记录TaskThatFails抛出内部的位置.
Adi*_*ter 54
您应该知道,自C#6.0以来,可以使用awaitin catch和finallyblocks,因此您实际上可以这样做:
try
{
// Do something
}
catch (Exception ex)
{
await DoCleanupAsync();
throw;
}
Run Code Online (Sandbox Code Playgroud)
新的C#6.0功能,包括我刚才提到的功能,在这里列出或作为视频在这里.
Ste*_*ary 16
如果您需要使用async错误处理程序,我建议这样的事情:
Exception exception = null;
try
{
...
}
catch (Exception ex)
{
exception = ex;
}
if (exception != null)
{
...
}
Run Code Online (Sandbox Code Playgroud)
同步阻塞async代码(无论它运行的是什么线程)的问题是你同步阻塞.在大多数情况下,最好使用它await.
更新:由于您需要重新抛出,您可以使用ExceptionDispatchInfo.