我应该为包含Thread的类实现IDisposable

时间:2012-10-29 15:01:50

标签: c# multithreading idisposable

我有一个使用Thread类的类:

class A
{
    public Thread thread
    { get; set; }
}

我应该实现IDisposable并将Thread属性设置为null吗?

class A : IDisposable
{
    public Thread Thread
    { get; set; }

    protected bool Disposed
    { get; set; }


    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.Disposed)
        {
            if (disposing)
            {
                if (Thread != null)
                    Thread = null;
            }

            Disposed = true;
        }
    }
}

还是不? 为什么呢?

2 个答案:

答案 0 :(得分:8)

仅当您的类处理非托管对象,资源或其他IDisposable对象时才实现IDisposable。线程不是非托管对象,并且在没有任何引用它时或者处理它的进程终止时将收集垃圾。由于Thread没有实现IDisposable,因此引用它的类也不需要实现它。

可选地,对于方法范围内的IDisposable,可以将它们包装在using语句中,并在退出范围时自动调用Dispose()方法。

答案 1 :(得分:2)

这取决于你的线程在做什么。如果您的线程正在执行可能无限期运行的长时间运行的任务,那么我会将线程视为资源(不会被垃圾回收)。例如,考虑线程是否被设计为无限期地轮询某个状态,或者从队列中消耗项目(如线程池线程消耗任务或TCP服务器消耗新连接)等。在这种情况下,我会说自然效果处理你的类将释放这个线程资源。在这种情况下,将其设置为null并不是很有用。相反,Dispose可能涉及标记同步事件(或者可能是CancellationToken)以通知线程它应该完成其无限任务,然后处置线程应该等待一段时间才能完成(加入)线程。与连接一样,请注意死锁情况,并在线程拒绝终止时考虑一些替代操作。出于显而易见的原因,我这样做会加入终结器。

作为我的意思的一个示例,请考虑您的class A实际为class MyTcpListener的情况,旨在监听并无限期地等待给定端口上的新TCP连接。然后考虑您希望遵循(稍微不太可能)的代码:

using (MyTcpListener listener = new MyTcpListener(port:1234))
{
    // Do something here
}

// Create another one. This would fail if the previous Dispose
// did not unbind from the port.
using (MyTcpListener listener = new MyTcpListener(port:1234))
{
    // Do something else here
}

假设我知道MyTcpListener的构造函数创建了一个监听器线程,我希望在Dispose调用返回后MyTcpListener不再绑定到TCP端口 - 即TCP侦听器线程将完全终止。不用说,如果你没有提供一些机制来阻止监听器会出现资源泄漏。停止机制可能是对某些方法“停止”的调用,但我个人认为“Dispose”模式更适合这种情况,因为忘记停止某些事情通常不会意味着资源泄漏。

您的代码可能会要求不同的假设,因此我建议您在该方案中对其进行判断。如果您的线程短时间运行,例如它有一些已知的有限任务要完成,然后它会自行终止,然后我会说处置不太重要或者可能没用。