2

VB.NETでAddHandlerの代わりにHandlesというキーワードを使用することの違いを検索しましたが、このコードが機能しない理由を説明できません。

Imports System.Threading
Public Class MyClass_EventArgs
    Inherits System.EventArgs
End Class

Public Class MyClass
    Public Event MainThreadFinished(ByVal sender As Object, ByVal e As MyClass_EventArgs)
    Private WithEvents MyEvents As MyClass
    Private trd As Thread
    Public Sub New()
        'AddHandler MainThreadFinished, AddressOf Me.MyEvents_ThreadFinished
        trd = New Thread(AddressOf mainThread)
        trd.IsBackground = True
        trd.Start()
        RaiseEvent MainThreadFinished(Me, Nothing)
    End Sub
    Protected Overrides Sub Finalize()
        trd.Abort()
    End Sub
    Protected Sub MyEvents_ThreadFinished(ByVal sender As Object, ByVal e As MyClass_EventArgs) _
                Handles MyEvents.MainThreadFinished
        MessageBox.Show("AAA")
    End Sub
    Private Sub mainThread()
        RaiseEvent MainThreadFinished(Me, Nothing)
    End Sub
End Class

このコードはイベントに応答しませんが、次の行のコメントを外すと、コードが機能し、メッセージボックスが表示されます...

'AddHandler MainThreadFinished, AddressOf Me.MyEvents_ThreadFinished

なぜこれが起こるのですか?

4

1 に答える 1

5

あなたは素晴らしい発見をしたようです!Microsoftのドキュメントによると、RaiseEventステートメント

非共有イベントは、それらが宣言されているクラスのコンストラクター内で発生させないでください。このようなイベントは実行時エラーを引き起こしませんが、関連するイベントハンドラーによってキャッチされない場合があります。Sharedコンストラクターからイベントを発生させる必要がある場合は、修飾子を使用して共有イベントを作成します。

言い換えれば、Microsoftは、自分がしていることをしてはいけないと言っています。そうしなければならない場合は、共有イベントを使用する必要があります。

AddHandler他の情報源を見ると、との違いはHandles糖衣構文の問題であると言えます。詳細については、C#でイベントがどのように行われるかを調べてください(C#イベントなど)。クラスのインスタンスがイベントを自動的にサブスクライブする方法Handlesとしてと組み合わせて使用​​されます(それ以外の場合は、C#およびVB.NETで明示的に実行されます)。WithEvents+=AddHander

明示的AddHandlerにイベントフックアップがの前に配置されていることを確認しているように見えるRaiseEventので、希望どおりに機能します。それがなければ、これらのイベントへの接続はまだ行われていなかったと推測できます。つまり、コンパイラがAddHandlerと同等のコードをバックグラウンドで挿入するため、コンパイラの作成者がどのようなデザインパターンを使用しても、機能しませんでした。適切と見なされます。これについての警告を考えると、設計者はこの起こりうる結果をよく知っていたようです。

于 2012-04-12T14:53:36.477 に答える