我有一些单元测试,以验证使用WeakReferences的对象是否正常工作。将这些对象重构为异步工作后,单元测试将失败。这似乎是由于使用异步时GC.WaitForPendingFinalizers无法工作(或工作方式不同?)引起的。
为了检查这一点,我创建了一个简单的WPF应用程序,其中包含两个按钮,一个带有常规Click事件,另一个带有异步Click事件。
当我按下NormalGCTest按钮时,将显示“收集的对象垃圾:真实”。
但是,当我按下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);
}
对我来说,它已经可以正常工作-我得到True
/ True
。但是,您可以尝试一些事情来澄清正在发生的事情-例如:
var wr = CreateWeakReference();
Console.WriteLine("object available: {0}", wr.Target != null);
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine("object garbage collected: {0}", wr.Target == null);
与
static WeakReference CreateWeakReference()
{
return new WeakReference(new object());
}
这会使用较少的局部变量,这可能会导致混淆,具体取决于编译器如何转换C#。它还使用了更具侵略性的GC.Collect
。
但重要的是:停止调用垃圾收集器。您几乎永远都不要这样做。最后的想法-您可能要避免async void
。是的,我知道这是一个事件处理程序,但是有一个不错的技巧是立即调用非async void
方法(await
必要时使用)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句