2013-08-14 4 views
0

Я проводил некоторые испытания с помощью COM Interop. Я экспортировал этот тестовый класс: -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, и она работает как что довольно странно. Обратите внимание, что граф будет вызван в рабочий поток, поэтому возникшее в нем событие должно быть поднято на рабочем потоке. Однако в VB6 я могу изменить заголовок Label от обработчика событий без проблем или сбоев, которых я не ожидал. Если бы это было сделано из VB.Net, это привело бы к исключению перекрестного потока. Мой вопрос: что происходит, когда класс используется из VB6? Содержит ли COM автоматически событие в потоке пользовательского интерфейса в приложении VB6? Или VB6 не заботится о том, чтобы элементы управления были изменены из рабочих потоков?

ответ

0

По умолчанию VB6 создает все его объекты в однопоточной квартире. Всякий раз, когда объект в VB6 передается в другой поток, он фактически передает копию объекта (известный как прокси).

Звонки на этот прокси-объект из фонового потока напрямую не обращаются к исходному объекту в потоке пользовательского интерфейса. Вместо этого они объединяются в вызовы по потоку пользовательского интерфейса через насос сообщений (используя в основном тот же механизм os Control.Invoke или SynchronizationContext.Send). Именно поэтому вы можете редактировать метки непосредственно, без необходимости ручного маршала вызова, сортировочный делаются для вас автоматически

Вот статья, которая обсуждает это в немного больше глубинах

+0

Спасибо за ваш информативный ответ Джаред. Итак, если я правильно понимаю, RaiseEvent на самом деле вызывает CountTick на прокси-сервере, который затем перенаправляет его обратно на реальный объект в своей квартире? – Niya

+0

@Niya, что будет в случае с vb6 – JaredPar

+0

Спасибо Джаред :) – Niya