0

I was doing some testing with COM Interop. I exported this test class:-

<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

I tested the above in VB6 and it works as is which is quite strange. Notice that Count would be called on a worker thread so the event raised therein should be raised on the worker thread. Yet in VB6 I am able to change a Label's caption from the event handler with no problems or glitches which I would not expect. If this were done from VB.Net, it would throw a cross thread exception. My question is, what is going on when the class is used from VB6 ? Does COM automatically raise the event on the UI thread in the VB6 app ? Or does VB6 not care about controls being altered from worker threads ?

4

1 回答 1

0

默认情况下,VB6 在一个单线程单元中创建它的所有对象。每当 VB6 中的对象被传递到另一个线程时,它实际上传递了该对象的副本(称为代理)。

从后台线程调用此代理对象不会直接调用 UI 线程上的原始对象。相反,它们通过消息泵被编组到 UI 线程上的调用中(使用基本相同的机制 osControl.InvokeSynchronizationContext.Send)。这就是为什么您可以直接编辑标签而无需手动编组呼叫的原因,编组是自动为您完成的

这是一篇更深入地讨论这个问题的文章

于 2013-08-14T06:29:38.963 回答