2012-02-01 49 views
0

私が起動した2つのスレッドのうちの1つのRunWorkerCompletedイベントが呼び出される方法によっては、奇妙な動作が発生しています。以下のコードと、スレッドgood、bad()を起動する2つの方法を確認してください。BackGroundWorker RunWorkerCompletedイベントが呼び出されない場合があります

Public Class Form1 

    Private WithEvents bw As System.ComponentModel.BackgroundWorker 
    Private WithEvents bw2 As System.ComponentModel.BackgroundWorker 
    Private starts As Integer = 0 

    Private Sub bw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork 
    starts += 1 
    Threading.Thread.Sleep(e.Argument) 
    End Sub 

    Private Sub bw_Completed(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted 
    MessageBox.Show("Ending " + starts.ToString()) 
    End Sub 

    Private Sub bad() 
    bw = New System.ComponentModel.BackgroundWorker() 
    bw.RunWorkerAsync(5000) 

    Threading.Thread.Sleep(500) 

    bw = New System.ComponentModel.BackgroundWorker() 
    bw.RunWorkerAsync(5) 
    End Sub 

    Private Sub good() 
    bw2 = New System.ComponentModel.BackgroundWorker() 
    AddHandler bw2.DoWork, AddressOf bw_DoWork 
    AddHandler bw2.RunWorkerCompleted, AddressOf bw_Completed 
    bw2.RunWorkerAsync(500) 

    bw2 = New System.ComponentModel.BackgroundWorker() 
    AddHandler bw2.DoWork, AddressOf bw_DoWork 
    AddHandler bw2.RunWorkerCompleted, AddressOf bw_Completed 
    bw2.RunWorkerAsync(5) 
    End Sub 

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 
    'good() 
    bad() 
    End Sub 
End Class 

どちらの場合でも、両方のスレッドに対してDoWorkイベントが呼び出されます。しかし、bad()の場合、2番目のスレッドだけがRunWorkerCompletedイベントを発生させます。これは明らかに私がここでイベントを処理するVBを使用している2つの異なる方法のためです。私はこの動作の説明を探しています。これらのイベントがVBでよりうまく処理されているかを理解するのに役立つドキュメンテーションへのリンクが必要です。ここで変数名を再利用するだけで、スレッドが処理される前に破棄されたり、イベントを起動するのを止めるように見えることは奇妙に思えます。

+1

実行中*のBackgroundWorker *への参照を置き換えています。確かに、WithEventsを介してその参照に添付されたイベントは、サブスクライブ解除されます。意図的に。 –

+0

ハンドラを追加するとき、私がやっていることとどう違うのですか?その参照も置き換えていますが、イベントは登録解除されません。この設計はどこに文書化されていますか? – user12861

+0

そのオブジェクト参照はWithEventsで宣言されていないため、自動登録解除は行われません。 –

答えて

1

この自動登録解除はどこに文書化されていますか?

Visual Basic言語仕様では、download from Microsoftというドキュメントがあります。第9.6.2項「WithEvents変数」には、次のように書かれています。

WithEvents宣言で作成された暗黙的なプロパティは、関連するイベントハンドラのフックとアンフックを行います。変数に値が代入されると、プロパティは、変数に現在あるインスタンスのイベントのremoveメソッドを最初に呼び出します(存在する場合は、既存のイベントハンドラのフックを解除します)。。次に、代入が行われ、プロパティの新しいインスタンスのイベントのaddメソッドが呼び出されます(新しいイベントハンドラがフックアップされます)。

太字の語句は、表示される動作を説明しています。それはそれがそのように機能することはかなり重要です。それがなかったらあなたは決してイベントから退会することができず、イベントの購読は無制限に積み重なるだろう。

+0

リンクとその理由をありがとう。まさに私が探していたもの。 – user12861

関連する問題