2012-06-18 17 views
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); 
} 

質問:ダウンロード()関数は、ファイルをダウンロードするのに長い時間がかかる場合、GCがでキックとRunWorkerCompleted前に労働者のオブジェクトを収集することができます()が実行されますか?

+0

デリゲート(Action(Of String)が行う)を使用し、BeginInvokeを呼び出すことをお勧めします。私は、このコードでBackgroundWorkerが必要ないとは思わない。メソッドが完了したときにイベントを添付することはできます。 – JDB

+1

これを行うより良い方法は、 'QueueUserWorkItem'を使用してスレッドプールキューに追加することです。http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx –

+0

@Jスレッドプールは素晴らしいですが、右のSynchronizationContext *でコールバック*を処理するのが難しくなります。 TPLはそれをうまく処理します。 –

答えて

12

は、あなたが実際の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に適さないため、このクラスのインスタンスがガベージコレクションされない可能性があります。

+0

これはOPの質問に対する答えではありません。まだ良いアドバイス。 – JDB

+1

@ Cyborgx37 OPの質問に直接答えを加えました。 –

+0

そのような変数を範囲外にすることは本当に良い考えですか?彼の後に来るプログラマーは、範囲内の変数が参照されることを期待していますが、どこかのエーテルにそこにあるいくつかのゾンビ変数ではありません。 –

関連する問題