5

Is there any way to execute a method of a com object inside a completely new thread, not attached to the main thread? I have tried using a backgrounWorker, and even using a new thread by doing Dim thr as new Thread(AddressOf blah) and neither work. I am not referencing the COM object anywhere but inside the threaded function "blah" or the backgroundWorker's DoWork method, yet still my main UI locks up as it tries to process the COM object's methods I am calling.

I really need to make this execute the methods from the com object in a separate thread because it is causing my whole application to lock up.

Below is an example of my Thread that uses a method "DoWork". The same logic can be taken for a background worker

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

Even though that should be running on a completely new thread, once it does scanner.open my main thread locks up till it is complete.

I appreciate any help.

Anthony Greco
  • 2,885
  • 4
  • 27
  • 39

2 Answers2

6

COM takes care of the object's threading requirements as published in the registry by the ThreadingModel registry key. Yours is obviously "Apartment", which makes COM take care of thread-safety on the object's behalf. That's very common. And yes, if you created it on the UI thread then COM marshals the call from your worker thread back to the UI thread.

To bypass that, you'd have to create a separate STA thread to give the object another thread-safe home. That requires creating a Thread, calling its SetApartmentState() method to make it STA and calling Application.Run() to run a message loop. That in itself is hard to deal with because you lose control, you'll want a Form or a Timer or Control.BeginInvoke() to generate events that let you use the object's methods. This is all pretty unpleasant, an hourglass cursor was popular in the olden days.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I have got to the point of all of that, besides Application.Run() part, but it still locked up when I created a new thread and set the appartment state to STA... I will attach my coding to better explain exactly what I am doing and the scanner.open line is what is locked up. Any suggestions? (editing my question after this to include my coding) – Anthony Greco Mar 21 '11 at 21:18
  • Not calling Application.Run in the thread is what makes it lock up. COM servers expect to be running on a thread that pumps a message loop, they depend on it. They'll use a timer for example. Check this (unsuitable) example: http://stackoverflow.com/questions/3641296/create-thread-just-like-if-it-were-a-separated-application-in-c/3642766#3642766 – Hans Passant Mar 21 '11 at 21:32
  • I managed to track down an all COM port connector source code I was able to tweak so that I did not need to use the external COM object. I am however sure this will eventually be a problem as I got to use 3rd party com objects all the time so I do appreciate the help and I will try that out next time I run into the issue. Thanks for the help! – Anthony Greco Mar 22 '11 at 06:24
0

Create the COM components in the worker thread so your COM methods won't be marhshalled to the Main UI thread.