【问题标题】:COM Interop and thread synchronizationCOM 互操作和线程同步
【发布时间】:2013-08-15 23:05:30
【问题描述】:

我正在使用 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 不关心从工作线程更改的控件?

【问题讨论】:

    标签: vb.net com


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢 Jared 提供的信息丰富的回答。因此,如果我理解正确,RaiseEvent 实际上会在代理上调用 CountTick,然后将其编组回其公寓中的真实对象?
    • @Niya 在 vb6 中就是这样
    猜你喜欢
    • 2017-04-28
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多