C# 我应该为包含线程的类实现IDisposable吗

C# 我应该为包含线程的类实现IDisposable吗,c#,multithreading,idisposable,C#,Multithreading,Idisposable,我有一个使用该类的类: 我应该实现IDisposable并将Thread属性设置为null吗 class A : IDisposable { public Thread Thread { get; set; } protected bool Disposed { get; set; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this

我有一个使用该类的类:

我应该实现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;
        }
    }
}
还是没有?

为什么?

只有当类处理非托管对象、资源或其他
IDisposable
对象时,才能实现
IDisposable
。线程不是非托管对象,当没有任何对象引用它或处理它的进程终止时,它将被垃圾收集。由于线程没有实现
IDisposable
,引用它的类也不需要实现它


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

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

作为我的意思的一个例子,考虑一下你的<代码>类A//COD>实际上是<代码>类MyTcPististNo/Cuff>,它被设计成在给定端口上无限期地监听和等待新的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”模式更适合这种情况,因为忘记停止某些东西通常并不意味着资源泄漏


您的代码可能需要不同的假设,因此我建议根据场景进行判断。如果您的线程运行时间较短,例如,它有一些已知的有限任务要完成,然后它将自行终止,那么我会说,disposing不那么重要,或者可能没有用处。

Dispose主要用于非托管资源。在您的情况下,当您的类超出范围时,您的
线程
对象最终将被垃圾收集。通常Dispose使用的空闲内存太快了…@rekire Nope,它不是,即使您尝试了,它也没有这种效果。(至少在您指的是托管内存时是这样。)@jgauffin Thread没有Dispose方法。@RobertHarvey您可以,从技术上讲,但它通常不会做您希望它做的事情。如果在多个方法的范围内使用该变量,那么即使可能,它也没有用处。它最终会在您使用资源之前处理掉它。大多数情况下是这样的,但是如果
Thread
实现了IDisposable,您可以使用
语句将其包装起来。无需在周围的类中重新实现IDisposable。@RobertHarvey线程的目的是执行异步操作,因此,如果您将线程包装在using语句中,并在其中启动线程,那么一旦启动线程,您的线程将立即被释放。可能线程尚未完成,它将立即被处理。因此,我不认为将线程对象包装在using语句周围是个好主意,即使你可以这样做。@Maarten:为什么线程一开始它就会被处理掉?只有当使用
语句退出
的范围时,它才应该被处理。@Marc AndréJutras:没错,但是如果你想启动你的线程“激发并忘记样式”,你不能使用
语句(在我们人为的假设中)将它包装在
中,因为它会在启动后立即被清理。@Maarten:这可能是
Thread
没有实现
IDisposable
的一个很好的原因:P
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
}