简体   繁体   English

C#,使用子线程删除对象时,GC没有调用析构函数

[英]C#, GC didn't call destructor when deleting an object with sub-thread

I'm having a problem in C#, when deleting an object which has a sub-thread running inside, GC doesn't call class destructor even if I add GC.WaitForPendingFinalizers(). 我在C#中遇到问题,删除一个内部运行有子线程的对象时,即使我添加GC.WaitForPendingFinalizers(),GC也不会调用类析构函数。 If I add _TC.Close() manually before _TC = null, destructor will be called properly, what's the reason cause this? 如果我在_TC = null之前手动添加_TC.Close(),则析构函数将被正确调用,这是什么原因引起的?

class Program
{
    static void Main(string[] args)
    {
        TestClass _TC;

        _TC = new TestClass();
        _TC = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.ReadKey();
    }
}

class TestClass
{
    Thread _T;
    bool _T_KeepWorking = true;
    public TestClass()
    {
        Console.WriteLine("TestClass Created.");
        _T = new Thread(new ThreadStart(Test_DoWork));
        _T.IsBackground = true;
        _T.Start();
    }

    ~TestClass()
    {
        Close();
        Console.WriteLine("TestClass Destroyed.");
    }

    public void Close()
    {
        _T_KeepWorking = false;
        if (_T.IsAlive)
        {
            _T.Join();
        }

    }

    public void Test_DoWork()
    {
        while (_T_KeepWorking)
        {
            Console.WriteLine("Test_DoWork alived.");
            Thread.Sleep(1000);
        }
    }

As you can read from the comments, most of the time you don't need destructor and your should prefer implementing IDisposable . 从注释中可以看出,大多数情况下,您不需要析构函数,而您应该更喜欢实现IDisposable Also lastest versions of the .NET framework introduce Task : .NET框架的最新版本还引入了Task

static void Main(string[] args)
{
    using (var testClass = new TestClass())
    {

    }

    Console.ReadKey();
}

class TestClass : IDisposable
{
    private Task _task;
    private CancellationTokenSource _cancellationTokenSource;
    public TestClass()
    {
        Console.WriteLine("TestClass Created.");
        _cancellationTokenSource = new CancellationTokenSource();
        _task = Task.Factory.StartNew(TestDoWork);
    }

    public void TestDoWork()
    {
        while (true)
        {
            if (_cancellationTokenSource.Token.IsCancellationRequested)
            {
                break;
            }
        }

        Console.WriteLine("Task Ended.");
    }

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

    // The bulk of the clean-up code is implemented in Dispose(bool)
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // free managed resources
            // Cancel the Task
            if (_cancellationTokenSource == null) return;

            _cancellationTokenSource.Cancel();
            _task.Wait();

            _cancellationTokenSource.Dispose();
            _cancellationTokenSource = null;
            _task = null;
            Console.WriteLine("TestClass Dispose.");
        }
        // free native resources here if there are any
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM