线程算作根对象;我不确切地知道 BackgroundWorker 是如何运作的,但主线程方法似乎很可能会访问工作实例上的状态;因此,工作线程本身将使 BackgroundWorker 实例保持活动状态,直到(至少)线程退出。
当然; 集合还要求所有其他(活动)对象都已取消引用工作对象;另请注意,堆栈变量的集合在调试/发布中可能不同,并且附加/不附加调试器。
[编辑] 如前所述;工作人员(在您的代码中)上的事件处理程序将使“视图”和“更新”对象保持活动状态(通过委托),但不是相反。只要工人的寿命比“视图”和“更新”短,您就不必对取消订阅事件感到偏执。我已经编辑了代码以包含一个“SomeTarget”对象,该对象仅由工作人员引用:您应该看到这种效果(即目标与工作人员一起死亡)。
当线程死亡时,重新工作人员被收集:这是证明;在工作人员报告退出后,您应该会看到“工作人员已完成”:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
class Demo : Form
{
class ChattyWorker : BackgroundWorker
{
~ChattyWorker()
{
Console.WriteLine("Worker finalized");
}
}
class SomeTarget
{
~SomeTarget()
{
Console.WriteLine("Target finalized");
}
public SomeTarget()
{
Console.WriteLine("Target created");
}
public void Foo(object sender, EventArgs args)
{
Console.WriteLine("Foo");
}
}
static void Collect(object sender, EventArgs args)
{
Console.WriteLine("Collecting...");
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 100;
timer.Tick += Collect;
timer.Start();
ChattyWorker worker = new ChattyWorker();
worker.RunWorkerCompleted += new SomeTarget().Foo;
worker.DoWork += delegate
{
Console.WriteLine("Worker starting");
for (int i = 0; i < 10; i++)
{
Thread.Sleep(250);
Console.WriteLine(i);
}
Console.WriteLine("Worker exiting");
};
worker.RunWorkerAsync();
}
[STAThread]
static void Main()
{ // using a form to force a sync context
Application.Run(new Demo());
}
}