背景工人和垃圾收集?

kar*_*hul 14 c#

我可以在方法中定义后台工作程序吗?

private void DownLoadFile(string fileLocation){
  BackgroundWorker worker = new BackgroundWorker();

  worker.DoWork += new DoWorkEventHandler((obj, args) => { 
      // Will be executed by back ground thread asynchronously.
      args.Result = Download(fileLocation);   
  });

  worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((obj, args) => { 
      // will be executed in the main thread.
      Result r = args.Result as Result;
      ReportResult(r);
   });

   worker.RunWorkerAsync(fileLocation);
}
Run Code Online (Sandbox Code Playgroud)

问题:如果Download()函数需要很长时间才能下载文件,那么在执行RunWorkerCompleted()之前,GC是否可以启动并收集工作对象?

Ree*_*sey 13

鉴于您实际上没有使用BackgroundWorker的大部分功能,我建议使用TPL代替:

private void DownLoadFile(string fileLocation)
{
    Task.Factory.StartNew( () => Download(fileLocation))
        .ContinueWith(t => ReportResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext());
}
Run Code Online (Sandbox Code Playgroud)

话虽这么说,worker对象一旦运行就不会被垃圾收集,因为ThreadPool线程本身会将worker保持为"使用过的对象".垃圾收集器将在完成事件处理程序执行之后才能收集它,此时将没有可以到达实例的用户代码BackgroundWorker.

此外,它可能会使此类的实例不被垃圾收集,因为ReportResults闭包使用的实例methods()使"this"的实例可以访问且不符合GC的条件.