c# - 如果任务的回调获取对实例本身的引用,实例是否会被垃圾收集?
问题描述
public class Cls
{
public object Obj { get; set; }
public async void Func()
{
Task.Run(() =>
{
Thread.Sleep(999999999);
this.Obj = new { };
});
}
}
public class Program
{
public static void Main(string[] args)
{
new Cls().Func();
}
}
请考虑上面的代码,如果它首先有意义,请忽略它。在上述情况下,我没有将实例存储Cls
到任何变量中,似乎没有引用该实例,它会是 GC。但是,有一个Task.Run()
在里面Func
。的回调函数Task
引用实例的Obj
属性。在这种情况下,我还能被 GC 收集吗?
我问这个问题是因为在SignalR的 Microsoft doc中它说
在调用依赖于集线器保持活动状态的异步方法时使用等待。
我不明白Hub
只要里面Clients.All.SendAsync
的东西引用了Hub
它自己,意志怎么会不存在……
谢谢。
解决方案
不,它不会被垃圾收集,因为您引用了this
in Task.Run()
(即使您this
在调用之前引用了 to Thead.Sleep()
)。
但是,如果您在 Azure Functions 中运行此代码,例如,框架可能会终止您的应用程序实例,并且回调中的代码将永远不会运行(不是因为被垃圾收集)。
顺便说一句,您可以通过调用GC.Collect()
执行垃圾收集的方法手动检查它是否被垃圾收集。
您可以使用此代码对其进行测试(例如,在 C# Interactive 中运行它)
static async Task Main(string[] args)
{
static void CreateObjectAndCallFunc()
{
var clsInstance = new Cls();
clsInstance.Func();
}
CreateObjectAndCallFunc();
Console.WriteLine($"before Task.Delay");
await Task.Delay(10);
Console.WriteLine($"after Task.Delay");
Console.WriteLine($"GC.Collect()");
GC.Collect();
Console.WriteLine($"after GC.Collect()");
Console.WriteLine($"before Task.Delay");
await Task.Delay(10);
Console.WriteLine($"after Task.Delay");
}
public class Cls
{
public Cls() { Console.WriteLine("Cls constructor"); }
~Cls() { Console.WriteLine("!!! Cls deconstructor"); }
public object Obj { get; set; }
public void Func()
{
Task.Run(() =>
{
System.Threading.Thread.Sleep(99999);
this.Obj = new object();
});
}
}
await Main(null);
如果你没有this.Obj
在 Task.Run(..) 中引用,那么它会输出这个:
Cls constructor
before Task.Delay
after Task.Delay
GC.Collect()
after GC.Collect()
before Task.Delay
!!! Cls deconstructor
after Task.Delay
但如果你这样做,它会输出这个:
Cls constructor
before Task.Delay
after Task.Delay
GC.Collect()
after GC.Collect()
before Task.Delay
after Task.Delay
推荐阅读
- python - Python - BeautifulSoup - 通过列表中的特定元素遍历 findall
- javascript - 如何在 HTML、CSS 和 Javascript(香草)中制作切换开关字
- html - 添加没有样式信息的类会导致重排吗?
- flutter - 如何将两种不同的方法分配给 Dart 中的单个变量?
- wpf - WPF 组合框 - 使用 ItemTemplate 连接时跳转到键入的字符
- html - 如何在 Cheerio 中选择元标签并获取内容值?
- certificate - 这个样本是如何伪造数字证书的
- physics - Godot - 在不破坏物理的情况下加快游戏速度
- javascript - 为什么我没有取回 useState 的新值 - React.JS?
- python - 出现错误“无法从 -vec generated/vectors/positives.vec 和 -bg generated/negatives.txt 创建图像阅读器。”