COM对象 - 线程 - .net

5
有没有办法在完全新的线程中执行 com 对象的方法,而不是附加到主线程?我已经尝试使用 backgrounWorker,甚至通过 Dim thr as new Thread(AddressOf blah) 使用新线程,但都不起作用。我只在“blah”线程函数或backgroundWorker的 DoWork 方法中调用 COM 对象的方法,但仍然会导致我的主 UI 锁定,因为它尝试处理我正在调用的 COM 对象的方法。

我真的需要让这个在单独的线程中执行来自 com 对象的方法,因为它导致整个应用程序锁定。

下面是一个使用方法“DoWork”的线程示例。相同的逻辑可以用于后台工作器

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.open 开始,我的主线程就会锁定直到它完成。
非常感谢任何帮助。
2个回答

6
COM将根据ThreadingModel注册表键发布的对象线程要求来处理对象的线程。您的显然是“Apartment”,这使得COM代表对象处理线程安全性。这很常见。是的,如果您在UI线程上创建它,那么COM会将调用从工作线程调度回UI线程。
为了绕过这个问题,您需要创建一个单独的STA线程,以给对象另一个线程安全的家。这需要创建一个Thread,调用它的SetApartmentState()方法以使其成为STA,并调用Application.Run()运行消息循环。这本身就很难处理,因为您失去了控制,您需要一个Form或Timer或Control.BeginInvoke()来生成事件,让您使用对象的方法。这一切都相当不愉快,在旧时代,沙漏光标很受欢迎。

我已经理解了所有内容,除了Application.Run()部分,但是当我创建一个新线程并将公寓状态设置为STA时,它仍然被锁定... 我会附上我的代码以更好地解释我正在做什么,scanner.open行就是被锁定的部分。有什么建议吗?(在此之后编辑我的问题以包括我的代码) - Anthony Greco
不在线程中调用Application.Run会导致程序锁死。COM服务器期望在一个泵送消息循环的线程上运行,他们依赖它。例如,他们将使用计时器。请检查此(不适当的)示例:http://stackoverflow.com/questions/3641296/create-thread-just-like-if-it-were-a-separated-application-in-c/3642766#3642766 - Hans Passant
我成功找到了一个全串口连接器源代码,我能够对其进行调整,以便我不需要使用外部COM对象。然而,我确信这最终会成为一个问题,因为我经常需要使用第三方COM对象,所以我很感激你的帮助,下次遇到这个问题时我会尝试使用它。谢谢你的帮助! - Anthony Greco

0
在工作线程中创建COM组件,这样你的COM方法就不会被调度到主UI线程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接