关于Task.Run会有内存泄漏风险的终结

关于Task.Run会有内存泄漏风险的终结

也不知道哪传来的Task.Run会有内存泄漏风险,开始在.NET圈子风靡,一时间大家都开始看看自己代码有没有存在这个问题。我也吃惊纳闷了一会,用自己的惯性思维思考了下.NET GC的基本工作原理:检查对象是否存在引用,不存在就会标记可回收,以及增加代数,并且会根据当前托管堆的内存使用情况来决定是否执行这些工作。

思来想去这个和异步有撒关系?按网上的说法还不仅仅是Task.Run,所有的异步方法都存在这个问题,咱.NET的GC有这么弱智?处理不了异步已过期对象?

参考大佬们的测试代码自己鼓捣一番,好家伙,还真回收不了?
引用:https://www.cnblogs.com/huangxincheng/p/14107100.html

看下这个测试代码,好像没毛病?错了,有毛病,最大的问题就是关于托管堆内存的使用情况,托管堆内存毫无压力的时候,GC才懒得理你。

优化他的测试代码,加点内存压力进去:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace GCCollectIntExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Test();
            Console.ReadLine();
        }

        static void Test()
        {
            for (int i = 0; i < 1000; i++)
            {
                var myClass = new MyClass();

                myClass.Foo();
            }
        }
    }

    public class MyClass
    {
        private int _id = 10;
        private List<Version> Versions { get; } = new List<Version>();

        public MyClass()
        {
            for (int i = 0; i < 100000; i++)
            {
                Versions.Add(new Version());
            }
        }


        public Task Foo()
        {
            return Task.Run(() =>
            {
                Console.WriteLine($"Task.Run is executing with ID {_id}");
            });
        }

        private static int Counter = 0;
        private static readonly object _locker = new object();

        ~MyClass()
        {
            lock (_locker)
            {
                Counter++;
            }
            Console.WriteLine($"Finalized, counter: {Counter}");
        }
    }
}

最后能得到输出:

Finalized, counter: 993
Finalized, counter: 994
Finalized, counter: 995
Task.Run is executing with ID 10
Task.Run is executing with ID 10
Task.Run is executing with ID 10
Finalized, counter: 996
Finalized, counter: 997
Finalized, counter: 998
Task.Run is executing with ID 10

释放掉了998个对象,每次执行这个数量可能不一致,完全是根据内存使用情况来的。

所以得出结论:放心大胆的用Task.Run,微软这点都考虑不到的话,那NETER还有什么前途。真正需要关注的是微软官方给出的内存泄漏注意点:https://docs.microsoft.com/zh-cn/aspnet/core/performance/memory?view=aspnetcore-5.0

原文地址:https://www.cnblogs.com/gucaocao/p/14179759.html