-1

我处于清理非托管资源是关键部分的情况。为了解决这个问题,我改变了这个......

void SomeMethod()
{
    //work
    using (var doc = SpreadsheetDocument.Open(results.FileName, true))
    {
        //use doc.
    }
}

对这个...

public static readonly object Locker = new object();
void SomeMethod()
{
    //work
    {//scoping doc
        var doc = SpreadsheetDocument.Open(results.FileName, true);
        try
        {
             //use doc
             //At some point wrapping a critical section via lock(Locker) 
        }
        finally
        {
            lock (Locker)
            {
                if (doc != null) ((IDisposable)doc).Dispose();
            }
        }
    }
}

我相信,这是一个丑陋而脆弱的解决方案。所以,我将其更改为以下...

public static readonly object Locker = new object();
void SomeMethod()
{
    //work
    CustomUsingWithLocker(SpreadsheetDocument.Open(results.FileName, true), Locker, doc =>
    {
        //use doc
        //At some point wrapping a critical section via lock(Locker) 
    });
}

public static void CustomUsingWithLocker<T>(T resource, object locker, Action<T> body)
    where T : class, IDisposable 
{
    try
    {
        body(resource);
    }
    finally
    {
        lock (locker)
        {
            if (resource != null) resource.Dispose();
        }
    }
}

这个定制解决方案是否可靠?我可以改进它吗?是否保证释放任何非托管资源,如内置的 Using 语句?

4

1 回答 1

0

这里的前提似乎Dispose是从多个线程中多次调用。如果是这种情况,请改变这个前提。即使doc被传递到......在另一个线程中使用它的某个地方,那个其他地方也不负责处理它,也不应该处理它。找到它在除末尾之外的位置using并将其更改为不这样做。

如果没有在其他地方被调用,并且您只是有一个不应该Dispose从多个线程访问的非线程安全Dispose方法(即使您的代码当前足够聪明,不会这样做)并且您只是想应用好防御性编程,我认为可以肯定地说这里不需要。在这个特定的上下文中,这个方法的一个有效约束是说只有一个线程应该负责处理对象。

于 2013-06-20T15:12:59.863 回答