2017-11-17 10 views
3

私はC#とWPFが初めてです。いくつかのコードを見直すために、オンラインドキュメントと例を読むのに何時間もかかりました。コードはSystem.Windows.Controls.Pageをサブクラス化し、バックグラウンド計算を行うにはBackgroundWorkerを使用します。ローカル変数でのみ参照されるBackgroundWorkerオブジェクトを作成するのが適切ですか?

私が学んだことから、この場合にはBackgroundWorkerオブジェクトを作成するための所望の方法、それはクラスのメンバ変数が参照するようにすることです。

例えば、

public class MyPage: System.Windows.Controls.Page 
{ 
    // Or: backgroundWorker = new System.ComponentModel.BackgroundWorker() 
    private System.ComponentModel.BackgroundWorker backgroundWorker; 
    .. 
} 

しかし、検討中のコードは、ローカル変数が参照するオブジェクトを作成します。

// Inside a class member function 
if (someCondition) 
{ 
    BackgroundWorker worker = new BackgroundWorker(); 
    worker.WorkerSupportsCancellation = true; 
    worker.WorkerReportsProgress = true; 
    worker.DoWork += new DoWorkEventHandler(DoWork1); 
    worker.DoWork += new DoWorkEventHandler(DoWork2); 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted); 
    worker.RunWorkerAsync(this.DataContext); 
} 

これは明確ですか? workerがオブジェクトに明白な唯一の参照であるので、スコープの外にあるオブジェクトはGCの対象となりますか?あるいは、フレームワークは、asnyc関数のコールバックのために余分な参照カウントを追加しますか?

「明確に定義されている」とは、ワーカーオブジェクトがすべてのコールバック(たとえば、RunWorkerCompleted)が終了するまで、メモリに常駐することが保証されていることを意味します。

ありがとうございます!

+0

それを試してみて、オブジェクトがまだ生きているかどうかを確認します。 – Enigmativity

+1

はい、問題ありません。しかし、あなたが証明を望むならば、上で示唆したように自分自身でテストすること(あるいは 'BackgroundWorker'を継承してファイナライザを追加すること)をGCに何度も強制し、ファイナライザがいつ呼び出されるか見ることができます。 – Evk

+0

これは問題ありませんが、二重のDoWork()はうんざりです。 –

答えて

3

RunWorkerAsync()メソッドを呼び出すと、BackgroundWorkerはすぐにガベージコレクションの対象になりません。あなた自身がWeakReferenceを使用してこれを確認することができます

BackgroundWorker worker = new BackgroundWorker(); 
worker.WorkerSupportsCancellation = true; 
worker.WorkerReportsProgress = true; 
worker.DoWork += new DoWorkEventHandler(DoWork1); 
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted); 
worker.RunWorkerAsync(); 

WeakReference viewModelWeakReference = new WeakReference(worker); 
worker = null; 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
MessageBox.Show(viewModelWeakReference.IsAlive.ToString()); 

あなたがRunWorkerAsync()呼び出した直後にそれを処分する場合であっても、それが完了するまで、それはまだ周りにハングします。 `弱い参照 `を作成し、GCを強制 - -

関連する問題