Luis Aguilar
Luis Aguilar

Reputation: 4381

Calling COM Interop API from a Background Thread?

I instantiate a service class that contains a COM interop component that does terminal automation. I am using Task Library (TPL) from Microsoft. I want to make calls to the COM object from a TPL task (background thread) so my UI doesn't freezes while the COM object is working.

However when I call my first function from the background thread (which receives an IntPtr) an COM Exception is thrown detailing HRESULT: 0xC0000005.

I know this is an access violation exception and I think I'm not mashaling my object the right way.

How can I call methods from a COM object created in the main thread from a background thread?

public void Button1_Click(object sender, EventArgs e) 
{
    var comWrapper = new COMWrapper(); // A simple wrapper for a COM object

    Task.Factory
        .StartNew(() => LoadStuff(comWrapper))
        .ContinueWith(() => {
            // Output results...
        });
}

int LoadStuff(COMWrapper w)
{
    return w.LoadStuffFromCOM();
}

Method that calls the COM object:

int LoadStuffFromCOM()
{
    string buffer;
    IntPtr pointer = Marshal.StringToHGlobalUni(buffer);

    return comObject.GetValue(pointer); // Exception here...
}

Upvotes: 0

Views: 1592

Answers (3)

Evalds Urtans
Evalds Urtans

Reputation: 6694

It is possible to have COM / OLE Interop objects running on background, but they must be compiled with correct Threading Model

In case of Delphi for MTA it should be compiled

initialization
  TTypedComObjectFactory.Create(ComServer, TSomeLogic, Class_SomeLogic,
    ciMultiInstance, tmFree);
end.

In case of STA by default it uses

initialization
  TTypedComObjectFactory.Create(ComServer, TSomeLogic, Class_SomeLogic,
    ciMultiInstance, tmApartment);
end.

It should be simmilar in C/C++ and other unmanaged languages

More information can be found here: http://msdn.microsoft.com/en-us/library/ff647812.aspx#scalenetchapt07 _topic11

Upvotes: 0

Jamie Pate
Jamie Pate

Reputation: 2062

IF you are desperate you could spawn a whole separate process which executed the com code. Then you would only have to write the ipc

Upvotes: 0

John Saunders
John Saunders

Reputation: 161781

Many legacy COM objects were made to run inside of a desktop application. That means they expected to run on the UI thread, with the Windows message pump as the only synchronizing method.

You're now trying to run that code in an environment it may never have "heard of". There's a good chance that you have violated the assumptions the author made when he wrote the code.

The code may work if you don't violate the assumptions, but if you do, then you're going to have a problem (or two, or two dozen).

Upvotes: 1

Related Questions