• 关于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

  • 相关阅读:
    selenium 等待时间
    将博客搬至CSDN
    关于科研和工作的几点思考
    窥探观察者模式
    泛型编程拾遗
    【opencv入门篇】 10个程序快速上手opencv【下】
    【opencv入门篇】 10个程序快速上手opencv【上】
    【opencv入门篇】快速在VS上配置opencv
    【MFC系列】MFC快速设置控件文本字体、大小、颜色、背景
    如何用Qt Creator输出helloworld
  • 原文地址:https://www.cnblogs.com/gucaocao/p/14179759.html
Copyright © 2020-2023  润新知