小心使用 Task.Run 续篇

关于前两天发布的文章:为什么要小心使用 Task.Run,对文中演示的示例到底会不会导致内存泄露,给很多人带来了疑惑。这点我必须向大家道歉,是我对导致内存泄漏的原因没描述和解释清楚,也没用实际的示例证实,是我的错。

但是,文中示例演示的 Task.Run 捕获类成员的情况,确实会有内存泄漏的风险,我将在本文演示给大家看。

如果一个对象(或数据)不需要再使用了,但依然还一直占据内存空间,则视为内存泄漏。这一点大家观点是一致的吧,那如何来检测对象有没有被回收呢?

我们知道,在 C# 中,实例对象被释放回收,必然会执行析构函数。所以我们可以对一个类重写其析构函数,如果该类的实例对象使用完后,强制执行 GC 回收,其析构函数依然不被执行,则说明 GC 没有回收该对象。若 GC 后面一直不回收这个对象,则说明存在内存泄漏。

手动强制执行 GC 回收的代码如下:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

这三句代码可以确保 GC 把所有能搜索到的可回收对象清理干净。注意:不推荐在生产环境这样写。

我们还是用 为什么要小心使用 Task.Run 这篇文章用到的示例,只是为了测试稍加修改了一下:

class Program
{static void Main(string[] args){Test();// 对不需要再使用的资源强制回收GC.Collect();GC.WaitForPendingFinalizers();GC.Collect();// 程序保活while (true){Thread.Sleep(100);}}static void Test(){var myClass = new MyClass();myClass.Foo();// 到这,myClass对象不需要再使用了}
}public class MyClass
{private int _id;private List<string> _list;public Task Foo(){return Task.Run(() =>{Console.WriteLine($"Task.Run is executing with ID {_id}");Thread.Sleep(100); // 模板耗时操作});}~MyClass(){Console.WriteLine("MyClass instance has been colleted.");}
}

我们在 myClass 对象使用完后,手动强制执行 GC 回收,运行结果如下:

我们看到 MyClass 的析构函数一直没有执行,也就意味着它的实例一直没有被回收。

现在我们修改 MyClass 类的 Foo 方法,改用本地(局部)变量试一试:

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

再运行看看效果:

这次我们可以看到,MyClass 的析构函数执行了,说明实例对象被回收了。

前后唯一区别是,前者在 Task.Run 的匿名方法中捕获了类的成员,而后者使用了本地变量。前者出现了内存泄漏,后者避免了内存泄漏。

所以,在 Task.Run 的匿名方法中捕获类的成员,确实有可能导致内存泄漏(注意是有可能而不是一定)。

那背后的原因是什么呢?我在上一篇文章是这样解释的:

私有成员 _id 被 Task.Run 的匿名方法捕获使用,进而导致 MyClass 实例被引用。当外部使用完 MyClass 实例时,本该由 GC 回收的时候却发现它还被其它资源引用着,所以 GC 认为该实例不应该被回收,也就可能永远失去了被回收的机会。

这个解释有很大的问题,至少给广大读者带来了两大疑惑:

  1. 由于值类型是拷贝的方式赋值,所以捕获的本地变量和类成员指向的是各自的值,对本地变量的捕获不会影响到整个类。但如果把 _id 改为引用类型(如 String),那两者指向的就是同一个对象值,那是不是意味着即便使用本地变量也还是无法避免内存泄漏的问题?

  2. GC 第一次回收时发现 myClass 实例存在被捕获的成员,则认为它不应该被回收。那当 Task.Run 执行完后, 被捕获的成员也使用完了,GC 再次搜索时不就可以回收 myClass 对象吗?只是晚了一些时间回收而已嘛。

感谢善于思考提出疑惑的读者们,为你们点赞。

这两大疑惑该如何解释?后半部分我还没写完,大家可以先思考一下,我将在下一篇给大家解惑,望大家见谅。当然,我的解释也不一定会是对的,希望大家带着怀疑的态度和批判性思维来看我的文章,也请大家分享自己的理解和观点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306476.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java实用教程——组件及事件处理——设置组件的位置(相对于窗口具体位置和布局)

1&#xff1a; 相对于窗口的具体位置 关键点&#xff1a; JButton组件添加到JPanel时&#xff0c;如果想自己位置&#xff0c;需要对JPanel进行如下设置&#xff0c;才能自定义按钮位置 需要将组件添加到画板上去&#xff0c;才可以设置组件的相对具体位置 button1.setBounds…

usb接口定义引脚说明_PerfDogService使用说明

令牌申请教程&#xff1a;https://bbs.perfdog.qq.com/article-detail.html?id55安装包下载&#xff1a;https://perfdog.qq.com/sdk一、 概述PerfDog性能狗服务组件&#xff0c;用户可基于service组件二次开发自己PerfDog性能工具或自动化服务。本文档主要对PerfDogService提…

java实用教程——组件及事件处理——布局管理(五种)

1.流式布局FlowLayout public void pack()调整此窗口的大小&#xff0c;以适合其子组件的首选大小和布局。如果该窗口或其所有者仍不可显示&#xff0c;则两者在计算首选大小之前变得可显示。在计算首选大小之后&#xff0c;将会验证该Window。窗口自动适应大小&#xff0c;使…

个人博客前端模板_腾讯前端开发工程师,教你极速搭建一个个人博客网站

作者&#xff1a; bookerzhao&#xff0c;腾讯 CSIG web前端开发工程师Github 为开源项目提供了用于静态页面展示的 Pages 服务&#xff0c;很多开发者都在上面托管了自己的静态网站和博客&#xff0c;不少开源项目的案例和文档页面也采用了这种方式。不过由于 Pages 的 CDN 节…

云原生时代 给予.NET的机会

.NET诞生于与Java的竞争&#xff0c;微软当年被罚款20亿美元。Java绝不仅仅是一种语言&#xff0c;它是COM的替代者&#xff01;而COM恰恰是Windows的编程模型。而Java编程很多时候比C编程要容易的多&#xff0c;更致命的是他是跨平台的。微软所推行.NET战略&#xff0c;并且C#…

java实用教程——组件及事件处理——布局的一个小实例

import javax.swing.*; import java.awt.*;public class BasicComponentDemo {Frame frame new Frame("这里测试基本组件");//定义一个按钮Button ok new Button("确认");//定义一个复选框组CheckboxGroup cbg new CheckboxGroup();//定义一个单选框&am…

非极大值抑制_非极大值抑制(non-maximum suppression)

摘自https://blog.csdn.net/qq_38906523/article/details/80195119摘自https://blog.csdn.net/xiexu911/article/details/80609298非极大值抑制NMS在目标检测&#xff0c;定位等领域是一种被广泛使用的方法。对于目标具体位置定位过程&#xff0c;不管是使用sliding Window还是…

TIOBE12月榜单:Java重回第二,Python有望四连冠年度语言

喜欢就关注我们吧&#xff01;文|白开水TIOBE 公布了 2020 年 12 月的编程语言排行榜。TIOBE 将在下个月公布 2020 年的年度编程语言&#xff0c;一年内排名率增长最高的编程语言将获得这一称号。目前&#xff0c;Python 以 1.90% 数据遥遥领先。其次分别是 C&#xff08;0.71%…

excel怎么在柱状图上加超链_如何让你的年终总结更符合领导心意,高薪员工必备的excel技能...

临近年底了&#xff0c;好多人都在写年终总结了&#xff0c;惯有的模式就是写一写这一年都做了哪些工作&#xff0c;有什么成绩&#xff0c;未来将如何完善等等......但是如何反应自己一年以来的成绩呢&#xff0c;如果单单是以文字的形式表述怕是不能让领导满意&#xff0c;甚…

java实用教程——组件及事件处理——对话框(dialog)

对话框&#xff1a; import java.awt.event.ActionEvent;import java.awt.event.ActionListener; import java.awt.*; import java.awt.event.*;public class DialogDemo1 {public static void main(String[] args) {Frame frame new Frame("这里测试Dialog");Di…

Vue 凭什么成为 2020 年的一匹黑马

Vue 在前端开发中的火爆程度远超 React 和 Angular &#xff0c;无论是 BAT 等大厂&#xff0c;还是小型初创公司&#xff0c;Vue 都有着广泛的应用&#xff0c;其相关技术原理也是面试的必考知识点。Vue 的优势太过明显&#xff1a;基于 HTML 的模板语法&#xff0c;响应式的更…

python——学习笔记1

推荐阅读&#xff1a; 爆肝十二万字《python从零到精通教程》 Python菜鸟教程 1.python 的输入输出&#xff1a; 输入&#xff1a;input() 输出&#xff1a;print() 输出不换行&#xff1a;print(x,end"") 数据要和字符串同时输出的时候需要将数据转化为字符串类…

开源C# Winform控件库《SunnyUI》强力推荐

本站(https://dotnet9.com)曾介绍过一款Winform开源控件库《HZHControls》&#xff0c;文章发布后不少朋友热情的咨询相关控件库信息&#xff0c;由此看来Winform在大家心中的地位还是挺高的。今天小编再分享一款新鲜出炉的 Winform 控件库库——SunnyUI&#xff0c;一起跟 Dot…

python——学习笔记2

python的数据结构 字符串&#xff1a; 字符串小写转大写&#xff1a; 字符串大写转小写&#xff1a; 删除空格&#xff1a; 空白是实际文本之前和/或之后的空间&#xff0c;通常您想删除这个空间。 strip()方法从开头或结尾删除任何空格&#xff1a; 替换字符串: replace()方…

庐山真面目之一 微服务的简介和技术栈

一、简介 这些年软件的设计规模越来越庞大&#xff0c;业务需求也越来越复杂&#xff0c;针对系统的性能、高吞吐率、高稳定性、高扩展等特性提出了更高的要求。可以说业务需求是软件架构能力的第一推动力&#xff0c;由于这些因素导致了软件架构思想和相关技术也在发生…

.net 读蓝牙数据_Linux内核曝严重蓝牙漏洞,影响多个版本

谷歌安全研究人员在Linux Kernel中发现了一组蓝牙漏洞(BleedingTooth)&#xff0c;该漏洞可能允许攻击者进行零点击攻击&#xff0c;运行任意代码或访问敏感信息。BleedingTooth漏洞分别被命名为CVE-2020-12351&#xff0c;CVE-2020-12352和CVE-2020-24490。其中最严重的漏洞是…

python——学习笔记3

日期&#xff1a; Python 日期和时间 函数&#xff1a; python 传不可变对象实例

算法题目——电梯(HDU-1008)

题目链接&#xff1a;HDU-1008 上楼&#xff1a;输入俩楼层之差 * 6s 停留层的5s 下楼&#xff1a;输入俩楼层之差 * 4s 停留层的5s #include<iostream> #include<vector>using namespace std; int main() {vector<int> vec;//用于存储每次的楼层数 vector…

.NET 云原生架构师训练营(模块二 基础巩固 引入)--学习笔记

2.1 引入http协议web server && web application framework.net 与 .net core asp .net coreweb api 示例CS&#xff1a;客户端-服务器BS&#xff1a;浏览器-服务器2.1.1 http协议请求过程消息结构请求方法状态码header请求过程1.URL解析2.DNS查询3.TCP连接4.处理请求5…

spss因子分析结果解读_因子分析巴特利特球形度检验结果解读

因子分析时&#xff0c;一般根据KMO和巴特利特检验的结果来判断数据是否适合做因子分析。那么巴特利特检验结果如何解读呢&#xff1f;既然是假设检验&#xff0c;必定有原假设和备择假设&#xff0c;只需要搞清楚假设是什么&#xff0c;也就知道应该如何解读了。百度百科上是这…