2012-03-04 17 views
4

のは、Windowsフォームの内側に、私はこのような長時間実行タスクを開始すると仮定しよう:フォームが閉じられた後、ThreadPool WaitCallbackがそれを呼び出すと、フォームはどうなりますか?

ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateDailyTasksChart)); 

次に、この機能はしばらくの間、実行されますが、それが終了する前に、私は、ウィンドウを閉じます。

private void UpdateDailyTasksChart (object param) 
{ 
    //Call Data Access Layer, go get MySQL Data. But I close the Form. 
    UICallback(chartData); //The Form is closed when this is executed. 
} 

そして今ここにUICallbackが何をするかです:

private delegate void UICallbackDel(object chartData); 
private void UICallback (object chartData) 
{ 
    if (InvokeRequired) 
    { 
    this.Invoke(new UICallbackDel(UICallback), chartData); 
    } 
    else 
    { 
    aButtonOnMyForm.Visible = false; //But the Form has been closed! 
    } 
} 

不思議なことに、このコードはクラッシュしません。

Form_Closedイベントにブレークポイントを設定しました。を実行します。フォームがまだ存在するかどうかは、たとえばクラス変数で宣言するなどしてチェックしていません。しかし、私の推測はそれがそうであるということです。

質問:私のスレッドが終了したときだけ、GCはフォームを収集するでしょうか?それとも何が起こるのですか?

+0

フォームは明示的に処理されていますか? – Jon

+0

これは事故によって動作します。フォームが破棄されたときにVisibleプロパティがすでにfalseになっているので、実際に何も実行されていないのは幸いです。爆弾は1ヶ月に1度のレースの可能性を排除するものではありません。 –

+0

@ハンスパッサント:フォームが処分されている場合は、Visibleプロパティにアクセスするだけでクラッシュしますね。とにかく、.Visible行は多くの中で1つだけです。私はそこでいくつかの他の機能を実行しています。スレッドが実行を終了し、それらの行のいずれもクラッシュしない場合、フォームにいくつかの変更が行われます。しかし、私はFormを明示的に処分しなかったので、Phongが言ったように、GCはまだその仕事をする必要はなかったので、Formは終了してスレッドが終了するのを待っています。どちらが迷惑です。私はThreadPoolをあきらめて、より多くの制御を可能にするThreadオブジェクトを使用する必要があります。 – Axonn

答えて

5

ここで2つの点があります。

  1. あなたが明示的にフォームを処分した場合、あなたが作業項目のデリゲートが実行されるときObjectDisposedExceptionを上げることを期待することがあります。
  2. 作業アイテムデリゲートは、this,InvokeRequiredthisを参照)とaButtonOnMyFormを参照して、フォームへの参照を保持します。したがって、ThreadPoolスレッドが実行を完了していない限り、フォームはガベージコレクションの対象になりません。そのため、コードがクラッシュすることはありません。 (注:。thisは関係なく、常に暗黙的にアクセス可能です)このことから導出する

もう一つは、そのフォームが閉じる前に、あなたがメモリリークを作成しないように、フォームからの外部イベントハンドラの登録を解除することが一般的に賢明であるということです。ラムダ式や匿名の代理人を登録すると、後で登録を解除するために参照を保存する必要があります。単に同じコードをコピーして貼り付けるだけでは機能しません。

+2

ありがとうございます。私は、スレッドオブジェクトまたはBackgroundWorkerを使用する必要がありますね。とにかく、ウィンドウが閉じられたときに中止することができます。 – Axonn

2

ポストthisをご覧ください。

基本的には、フォームに呼び出すときにGCが何をしているかによって、ObjectDisposedExceptionが得られる場合もあれば、得られない場合もあります。あなたは試してみることができますが、それを確実にテストすることはできませんので、それは何よりもハックです。

+0

それは意味をなさない。まだフォームへの参照がある場合は、GCが何を行うのかは明らかです。何もありません。 – svick

2

ガベージコレクタは、オブジェクトが「閉じられている」、「破棄された」かどうかは気にしません。オブジェクトにまだアクセスできるかどうかだけが気にします。あなたの場合、フォームはthis(暗黙的または明示的)を使用して引き続きアクセスできます。そのため、アプリケーションがクラッシュすることはありません。

もちろん、オブジェクトがクローズまたは破棄されている場合などは、オブジェクトを呼び出すメソッドに対してObjectDisposedExceptionなどを投げる権利があります。しかし確かにそれをする必要はありません。

+0

私は明示的に処分するのは好きではないので、おそらく「不合理な」スレッドを使用して解決します。 – Axonn

+0

'Thread.Abort()'を呼び出すことを意味しない限り、動作するはずです。 – svick

+1

それはまさに私が意味していたものです。なぜそれはいいのではないですか?私にとっては、グラフは、重要な操作ではないため、ユーザーがスレッドを完了するよりもウィンドウを閉じることができるようにすることが重要です。ユーザーがウィンドウを閉じると、私はすべてをあきらめ、それだけです。 – Axonn

関連する問題