本文介绍了析构函数中的异步操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试在类析构函数中运行异步操作失败.

Trying to run async operation in class destructor is fail.

这是代码:

public class Executor
    {
        public static void Main()
        {
            var c1 = new Class1();

            c1.DoSomething();
        }
    }

    public class Class1
    {
        public void DoSomething()
        {

        }

        private int _i = 100;
        private int _j = 100;

        ~Class1()
        {
            Task.Run(() => _j *= 2); //Does not progress _j
            _i *= 2; //Progress _i from 100 to 200

            Thread.Sleep(1000);
            Console.WriteLine("In destructor. _i = " + _i);
            Console.WriteLine("In destructor. _j =  " + _j);
        }
    }

输出为:

In destructor. _i = 200
In destructor. _j =  100

以下 MSDN上的析构函数页面没有提到线程/异步实例销毁的各个方面.

Following Destructor page on MSDN does not mention threads/async aspects of instance destruction.

有什么想法吗?

谢谢

推荐答案

在您的特定示例中,由于运行时正在终止并且应用程序域正在卸载,因此无法启动新线程.当应用程序域卸载时,它将运行所有终结器并关闭所有线程.您可以使用以下方法进行验证:

In your particular example new thread cannot be started because runtime is terminating and app domain is unloading. When app domain unloads - it will run all finalizers and shutdown all threads. You can verify this with:

Console.WriteLine("shutdown:" + Environment.HasShutdownStarted);

在您的情况下,哪个将返回 true .如果您修改示例,如下所示:

Which will return true in your case. If you modify you example like this:

class Program {
    static void Main(string[] args) {
        var c1 = new Class1();
        c1.DoSomething();
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.ReadKey();
    }
}

public class Class1
{
    public void DoSomething()
    {

    }

    private volatile int _i = 100;
    private volatile int _j = 100;

    ~Class1()
    {
        Console.WriteLine("shutdown:" + Environment.HasShutdownStarted);
        Task.Run(() => _j *= 2); //Does not progress _j
        //_i *= 2; //Progress _i from 100 to 200
        Thread.Sleep(1000);
        Console.WriteLine("In destructor. _i = " + _i);
        Console.WriteLine("In destructor. _j =  " + _j);
    }
}

并以优化方式在发布模式下进行编译-您将看到现在运行时没有终止,您的任务将正常运行.

And compile in Release mode with optimizations - you will see that now runtime is not terminating and your task will run fine.

很显然,您永远不要在终结器中执行此类操作,而要知道真正的原因.

Obviously you should never do such things in finalizer, but just so that you know the real reason.

这篇关于析构函数中的异步操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 00:30