背景工人和垃圾收集?

时间:2012-06-18 18:17:18

标签: 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);
}

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

1 个答案:

答案 0 :(得分:12)

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

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

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

此外,它可能会使此类的实例不被垃圾收集,因为闭包使用的实例方法(ReportResults)使“this”实例可以访问且不符合GC的条件。< / p>