6

我有一个使用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;
        }
    }
}

或不?
为什么?

4

2 回答 2

8

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

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

于 2012-10-29T15:04:17.110 回答
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 侦听器线程将完全终止。不用说,如果您不提供某种机制来阻止侦听器,就会发生资源泄漏。停止机制可能是对某些方法“Stop”的调用,但我个人认为“Dispose”模式更适合这种情况,因为忘记停止某些东西通常并不意味着资源泄漏。

您的代码可能需要不同的假设,所以我建议根据场景来判断它。如果你的线程是短期运行的,例如它有一些已知的有限任务要完成,然后它会自行终止,那么我会说处置不那么重要或者可能没用。

于 2012-10-29T15:54:12.693 回答