14

我可以在方法中定义后台工作人员吗?

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对象吗?

4

1 回答 1

13

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

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

话虽如此,worker对象一旦运行就不会被垃圾回收,因为 ThreadPool 线程本身会将 worker 保持为“已使用对象”。直到完成事件处理程序执行之后,垃圾收集器才能收集它,此时将没有用户代码可以到达BackgroundWorker.

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

于 2012-06-18T18:23:57.513 回答