有没有办法在一个全新的线程中执行一个com对象的方法,而不是附加到主线程?我尝试过使用backgrounWorker,甚至通过Dim thr as new Thread(AddressOf blah)
使用新线程,但都没有工作。我没有在任何地方引用COM对象,而是在线程函数“blah”或backgroundWorker的DoWork方法中,但是当我尝试处理我调用的COM对象的方法时,我的主UI仍然锁定。
我真的需要让它在一个单独的线程中执行来自com对象的方法,因为它导致我的整个应用程序被锁定。
下面是我使用“DoWork”方法的Thread的示例。可以为后台工作者采用相同的逻辑
Public Sub Reconnect_Scanner() Implements Scanners.Reconnect_Scanner
'Do our request on a new thread
Dim thread As New System.Threading.Thread(AddressOf Connect)
thread.SetApartmentState(Threading.ApartmentState.STA)
thread.Start()
End Sub
Public Sub Connect()
'Get a new instance of our scanner
Dim scanner As New OposScanner_CCO.OPOSScanner
'Loop until scanner is opened
Do
Debug.Print("looking for scanner")
'If we find the device, exit do
Dim openId As Integer = scanner.Open("Honeywell")
If openId = 0 Then Exit Do
'Sleep 1 second
System.Threading.Thread.Sleep(250)
Loop
End Sub
即使它应该在一个全新的线程上运行,一旦它执行scanner。打开我的主线程直到它完成。
我感谢任何帮助。
答案 0 :(得分:6)
COM负责处理ThreadingModel注册表项在注册表中发布的对象的线程要求。你的显然是“公寓”,这使得COM代表对象处理线程安全。这很常见。是的,如果你在UI线程上创建了它,那么COM将你的工作线程的调用编组回UI线程。
要绕过它,您必须创建一个单独的STA线程,以便为该对象提供另一个线程安全的主页。这需要创建一个Thread,调用它的SetApartmentState()方法使其成为STA并调用Application.Run()来运行消息循环。这本身很难处理,因为你失去控制,你需要一个Form或Timer或Control.BeginInvoke()来生成让你使用对象方法的事件。这一切都非常不愉快,沙漏光标在过去很受欢迎。
答案 1 :(得分:0)
在工作线程中创建COM组件,这样您的COM方法就不会被marhshalled到主UI线程。