COM互操作和线程同步 [英] COM Interop and thread synchronization

查看:53
本文介绍了COM互操作和线程同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用COM Interop进行一些测试.我导出了这个测试类:-

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

我在VB6中测试了上面的内容,它按原样工作,这很奇怪.注意,将在工作线程上调用Count,因此引发在其中的事件应在工作线程上引发.但是在VB6中,我可以从事件处理程序中更改Label的标题,而不会出现我不希望出现的问题或小故障.如果从VB.Net完成此操作,则将引发跨线程异常.我的问题是,从VB6使用该类时会发生什么情况?COM是否会在VB6应用程序的UI线程上自动引发事件?还是VB6不在乎控件是否从工作线程中更改?

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 ?

推荐答案

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

By default VB6 creates all of it's objects in a single threaded apartment. Whenever an object in VB6 is passed to another thread it actually passes a copy of the object (known as a proxy).

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

Calls to this proxy object from a background thread don't directly call into the original object on the UI thread. Instead they are marshalled into calls on the UI thread through the message pump (using basically the same mechanism os Control.Invoke or SynchronizationContext.Send). This is why you can edit labels directly without having to hand marshal the call, the marshalling is done for you automatically

这里有一篇文章对此进行了更深入的讨论

Here is an article which discusses this in a bit more depth

这篇关于COM互操作和线程同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆