【发布时间】:2014-02-21 15:38:19
【问题描述】:
我有一些单元测试来验证使用 WeakReferences 的对象是否正常工作。在将这些对象重构为异步工作后,单元测试会失败。这似乎是由于使用异步时 GC.WaitForPendingFinalizers 不工作(或工作方式不同?)引起的。
为了检查这一点,我创建了一个带有两个按钮的简单 WPF 应用程序,一个带有常规 Click 事件,一个带有异步点击事件。
当我按下 NormalGCTest 按钮时,会显示“收集的对象垃圾:True”。
但是当我按下 AsyncGCTest 按钮时,会显示“收集的对象垃圾:False”。
发生了什么事?有没有办法在我的测试中强制进行完整的垃圾回收?
private void NormalGCTest(object sender, RoutedEventArgs e)
{
var temp1 = new object();
var temp2 = new WeakReference(temp1);
temp1 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
temp1 = temp2.Target;
System.Diagnostics.Debug.WriteLine("object garbage collected: {0}", temp1 == null);
}
private async void AsyncGCTest(object sender, RoutedEventArgs e)
{
var temp1 = new object();
var temp2 = new WeakReference(temp1);
temp1 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
temp1 = temp2.Target;
System.Diagnostics.Debug.WriteLine("object garbage collected: {0}", temp1 == null);
await Task.Delay(0);
}
【问题讨论】:
-
可能由于某种原因,生成的闭包类仍然引用了 temp1。我不知道 async/await 可能保证的任何 GC 属性。 IOW 无法保证 C# 语言在调用 Collect 时 temp1 已死。
-
不建议显式调用 GC。你确定你需要它?顺便说一句,AFAIK GC 适用于所有线程(清理时停止所有线程)。结合 async 使用感觉有点奇怪。
-
在控制台应用程序中,两者都对我有用...您是否在调试器下运行?这很可能会有所作为。
-
在本地运行它,我得到
True,True- 它被双向收集 -
@PetarRepac 这是一个涉及弱引用的单元测试,所以当然需要调用GC。我不认为它是在实际代码中调用的。
标签: c# wpf garbage-collection async-await