1

我正在创建一个类,比如 LockHolder,以简化需要逻辑的锁。它实现了 IDisposable 接口,因此我可以像这样使用它:

using(LockHolderCreater.Create(lockObject, waittime))
{
    //do something
}

LockHolder 的 Dispose 方法释放 lockObject(通过 Monitor.Exit)如果已获得(通过 Monitor.TryEnter)。如果我每次调用 LockHolderCreater.Create 时都创建一个新的 LockHolder 对象,那效果很好,但这会创建太多的 LockHolder 实例。所以我写了 LockHolderCreater 来维护一个 LockHolder 对象的列表,以便重用它们。现在我也面临着问题:

首先,在调试时,我发现在输出窗口中有很多诸如“System.dll 中发生'System.ObjectDisposedException' 类型的第一次机会异常”这样的消息。如果“using”语句所做的只是调用Dispose方法,我可以防止这种异常吗?

其次,更重要的是,如果我重用 LockerHolder 实例,在我的应用程序启动后的某个早期时间,当我尝试在 Dispose 方法中释放锁时会抛出 SynchronizationLockException 异常,说“对象同步方法是从不同步的代码块。”。我检查了我的逻辑,但我认为两个线程不可能同时使用一个 LockHolder 实例。这可能与上面提到的 ObjectDisposedException 有关吗?

关于答案

我没有得到我的问题的直接答案,但 Marc Gravell 的回答使它变得不那么必要了。

4

3 回答 3

3

您是否应该这样做:可能不会,除非您完全控制类型的非常特殊的情况。

你能做到吗:这完全取决于实现 - 你当然不想将它随机应用于任意类型。但是,如果该类型(作为清理的一部分)返回到某个池并重新初始化和重新使用,那么是的,它将起作用。但是:如果 // do something代码在某处泄露了引用,您将面临问题。

我可以防止这种异常吗?

是的:在你处理它之后不要访问它

说“对象同步方法是从不同步的代码块中调用的。”

我想知道 - 你也许await在这里使用?还是迭代器块?或类似的东西?如果进入和退出代码在不同的线程上运行,它将失败。

如果您的意图是尽量减少 的分配LockerHolder,有一个更好的方法:使用struct

using System;

struct Foo : IDisposable
{
    public Foo(string msg)
    {
        Console.WriteLine("Init: " + msg);
    }
    public void Dispose()
    {
        Console.WriteLine("Disposed");
    }

}

static class Program
{
    static void Main()
    {
        Console.WriteLine("Before");
        using (new Foo("Hi"))
        {
            Console.WriteLine("Do stuff");
        }
        Console.WriteLine("After");
    }
}

这里的Main方法编译Disposeusing constrained-call,这意味着它不会 box

请注意,要使其正常工作,该LockHolderCreater.Create方法必须返回结构本身 - 它不能只返回IDisposable.

于 2013-11-05T11:39:53.570 回答
0

滥用该using声明是个坏主意。它不打算用作通用的“自动撤消”。它仅用作确保处置非托管资源(如数据库连接)的一种手段。

于 2013-11-05T11:38:52.410 回答
0

在 using 语句的控制表达式内声明变量会将变量的范围限制在 using 语句内。

检查这个答案

于 2013-11-05T11:36:41.143 回答