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()関数がファイルのダウンロードに長い時間がかかる場合、RunWorkerCompleted()が実行される前にGCが起動してワーカーオブジェクトを収集できますか?

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 スレッド自体がワーカーを「使用済みオブジェクト」として保持するため、オブジェクトは一度実行されるとガベージ コレクションされません。ガベージ コレクターは、完了イベント ハンドラーが実行されるまでそれを収集できません。この時点では、 のインスタンスに到達できるユーザー コードはありませんBackgroundWorker

さらに、ReportResultsクロージャによって使用されるインスタンス メソッド ( ) が「this」のインスタンスにアクセス可能であり、GC の対象にならないため、このクラスのインスタンスがガベージ コレクションされないようにする可能性があります。

于 2012-06-18T18:23:57.513 に答える