Search code examples
c#comtask-parallel-library

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...
}

Solution

  • 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