我有以下功能:
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
SomeLegacySynchronousCode(session);
await m_sessionProvider.EndSessionAsync(session);
}
其中
EndSessionAsync
记录并吞下任何异常(就像一个好的析构函数)。问题是
SomeLegacySynchronousCode
可能会抛出异常,然后 session 泄漏。我很清楚为什么以下代码是非法的:
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
try
{
SomeLegacySynchronousCode(session);
}
finally
{
await m_sessionProvider.EndSessionAsync(session);
}
}
所以,我正在寻找一种既正确又优雅的替代方案。
变体 I
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
Exception exc = null;
try
{
SomeLegacySynchronousCode(session);
}
catch (Exception e)
{
exc = e;
}
await m_sessionProvider.EndSessionAsync(session);
if (exc != null)
{
// Wrap to preserve the original stack trace.
throw new AggregateException(exc);
}
}
变体 II
private Task DoSomething(NamespaceConnectionInfo nci)
{
return m_sessionProvider.GetSessionAsync(nci).ContinueWith(t =>
{
Task result = null;
try
{
SomeLegacySynchronousCode(t.Result);
}
finally
{
if (t.Exception == null)
{
result = m_sessionProvider.EndSessionAsync(t.Result);
}
}
return result;
}).Unwrap();
}
两者都不如前面提到的非法 async/await 版本那么优雅。
我希望改进我提出的两个变体,因为坦率地说,它们都很丑陋。
有任何想法吗?
最佳答案
commonly-accepted answer 似乎与您的变体 1 相似:
关于c# - 寻找一种优雅的方式来绕过 "Cannot await in the body of a finally clause",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22391121/