在Dispose()中处理异常

时间:2016-05-24 09:35:27

标签: c# error-handling marshalling dispose

我有一个UnitOfWork类,它根据块中的错误提交或回滚事务。

class UnitOfWork: IDispose
{
        public void Dispose()
        {
                if (Marshal.GetExceptionCode() == 0 
                   || Marshal.GetExceptionPointers() == IntPtr.Zero)
                {
                       // Commit
                }
                else
                {
                      // Rollback
                }
            }
        } 
}

此类以下列方式使用:

try
{
    using (var uow = new UnitOfWork())
    {
        // Do something here that causes an exception
    }
}
catch
{
    using (var uow = new UnitOfWork())
    {
        // Log exception
    }
}

我已经阅读了这篇文章: Detecting a Dispose() from an exception inside using block

在上面的问题中,Steven(其中一位回复的人)提到,如果我在Dispose()中为“try”部分中的“using”块检测到异常,我就无法创建另一个UnitOfWork类。 “catch”阻塞并将错误记录到数据库中(因为Dispose()中的“Marshal”代码将继续说有异常),这意味着ExceptionCode和ExceptionPointers将从try块“浮动”(?)到catch块。

然而,在我的情况下,这是正常的 - 即。如果“try”部分的“using(var uow = new UOW)”块中有异常,它会正确捕获异常,然后在catch块中传递“if”条件,导致提交发生并允许我记录异常。

归结为我对Marshal.GetExceptionPointers()的工作原理有不完全的理解。有人可以确认我的使用模式是否正常工作(到目前为止所有测试似乎都表明它正常工作)以及Marshal.GetExceptionPointers()究竟在做什么?

1 个答案:

答案 0 :(得分:1)

IDisposable.Dispose旨在释放资源,将提交/回滚操作放入其中是一个坏主意。调用者应该知道如何处理异常以及如何回滚。

using (var unitOfWork = new UnitOfWork())
{
    try
    {
        Prepare();
        Step1();
        Step2();
        unitOfWork.Commit();
    }
    catch(PrepareException e)
    {
        //no necessary to rollback, just log it
    }
    catch(FirstStepException e1)
    {
        //rollback step1
    }
    catch(SecondStepException e2)
    {
        //rollback step1 and step2
    }
}