views:

79

answers:

3

I'm using com interop to talk to some physical piece of hardware.

When I need the current reading from the hardware I have a nice elaborate piece of threading code that keeps it off my UI thread so that I don't lock up the UI while I query the hardware since sometimes it can take as much as 1-2 minutes (although usually more like 1-5 seconds).

So once I step into the com object it bounces back to the main UI thread and the UI becomes busy during the duration of the reading.

The main app is a .net WPF app, so it STA by default. The COM object is created on the main thread, but it's created my a singleton factory, so all of these objects are created by the same few lines of UI.

I'd love to show some code, but it's not like the stuff is in just a few lines of code.

What kind of work arounds are there for this behavior? I'd also love to be able to read from multiple com object simultaneously.

If were to create background threads to spin up these com objects inside my object facotry. How do I keep them alive to handle the work that gets marshaled back to them?

+1  A: 

Assuming the object is apartment threaded - make sure you call it on the same thread that created it. Otherwise the calls will be routed to the object's home thread via Windows messages, thus blocking the UI.

If everything else fails - spawn a worker process.

EDIT: and another point - the worker thread needs to be an STA, and needs a message loop. Otherwise the object lives in the main thread, with routing and UI blocking.

Seva Alekseyev
I don't think I can even have the worker process accomplish what I need.
Joel Barsotti
A: 

"I have a nice elaborate piece of threading code" - This has a 'famous last words' ring to it.

"The COM object is created on the main thread, but it's created my a singleton factory, so all of these objects are created by the same few lines of UI."

If your COM object was created in your GUI thread, why are you surprised when it blocks the GUI thread? Why not create the COM object in the thread that directly talks to the hardware?

Jim In Texas
Well maybe eleborate is the wrong phrase.I'm suprised because I can create any native .net object and it will either execute the method I call in the background thread or it will throw an exception because it's not on the main thread.
Joel Barsotti
Do you have a tutorial you can refrence on how to create objects on a seperate thread?Does that thread stay alive after the object creation has occoured?
Joel Barsotti
+1  A: 

I have it working.

Previously my constructor worked like:

internal class Device
{
    private ComDeviceLibrary.UberDevice myDevice;

    internal Device(DeviceInitObject myInitOptions)
    {
        myDevice = new ComDeviceLibrary.UberDevice();
    }
}

Now if I do this:

internal class Device
{
    private ComDeviceLibrary.UberDevice myDevice;

    internal Device(DeviceInitObject myInitOptions)
    {

        AutoResetEvent createHandle = new AutoResetEvent(false);
        Thread creationThread = new Thread(CreateDevice);
        creationThread.IsBackground = false;
        creationThread.SetApartmentState(ApartmentState.MTA);
        creationThread.Start(createHandle);
        createHandle.WaitOne();
    }

    private void CreateDevice(object objWaitHandle)
    {

        myDevice = new ComDeviceLibrary.UberDevice();
        ((AutoResetEvent)objWaitHandle).Set();
    }
}

It works!

Joel Barsotti
Hmya, what you're doing is highly illegal in the COM apartment threading model. You might get away with it, just make sure you *never* make a method call on this object from another thread.
Hans Passant
All I do is make calls on it from other threads.
Joel Barsotti
Also if I do this with the apartment model set to STA then it sorta rolls over.
Joel Barsotti