我有以下功能:

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/

10-12 01:46