0

COM Interop でいくつかのテストを行っていました。このテストクラスをエクスポートしました:-

<ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(GetType(ICounterEvents))> _
Public Class Counter
Implements ICounter

Public Event CountTicked(ByVal current As Integer, ByVal max As Integer)

Public Sub StartCount(ByVal max As Integer) Implements ICounter.StartCount
    ThreadPool.QueueUserWorkItem(Sub() Count(max))
End Sub

Private Sub Count(ByVal max As Integer)

    For i = 1 To max
        Dim x As Integer = i

        'COM Seems to synchronize this automatically
        RaiseEvent CountTicked(x, max)

        Thread.Sleep(300)
    Next


End Sub


End Class

上記をVB6でテストしたところ、そのまま動作しますが、これは非常に奇妙です。Count はワーカー スレッドで呼び出されるため、そこで発生したイベントはワーカー スレッドで発生する必要があることに注意してください。しかし、VB6 では、ラベルのキャプションをイベント ハンドラから問題なく変更でき、予期しない問題も発生しません。これが VB.Net から実行された場合、クロス スレッド例外がスローされます。私の質問は、クラスが VB6 から使用されるとどうなりますか? COM は VB6 アプリの UI スレッドでイベントを自動的に発生させますか? それとも、VB6 はワーカー スレッドから変更されたコントロールを気にしませんか?

4

1 に答える 1

0

デフォルトでは、VB6 はすべてのオブジェクトを単一のスレッド化されたアパートメントに作成します。VB6 のオブジェクトが別のスレッドに渡されるときはいつでも、実際にはオブジェクトのコピー (プロキシと呼ばれます) が渡されます。

バックグラウンド スレッドからこのプロキシ オブジェクトを呼び出しても、UI スレッド上の元のオブジェクトは直接呼び出されません。代わりに、メッセージ ポンプを介して UI スレッドの呼び出しにマーシャリングされます (基本的に同じメカニズム osControl.Invokeまたはを使用しますSynchronizationContext.Send)。これが、呼び出しを手動でマーシャリングしなくてもラベルを直接編集できる理由です。マーシャリングは自動的に行われます。

これについてもう少し詳しく説明している記事があります

于 2013-08-14T06:29:38.963 に答える