C# Marshalling COM objects between threads

北城以北 提交于 2019-12-04 12:58:31
noseratio

It appears you're using Stephen Toub's StaTaskScheduler as a part of some "stateful" logic, where your COM objects live across StartNew boundaries. If that's the case, make sure you create and use these objects on the same StaTaskScheduler STA thread and nowhere outside it. Then you wouldn't have to worry about COM marshaling at all. Needless to say, you should create StaTaskScheduler with only one thread, i.e., numberOfThreads:1.

Here's what I mean:

var sta = new StaTaskScheduler(numberOfThreads:1);

var comObjects = new { Obj = (ComObject)null };

Task.Factory.StartNew(() =>
{
    // create COM object
    comObjects.Obj = (ComObject)Activator.CreateInstance(
        Type.GetTypeFromProgID("Client.ProgID"));
}, CancellationToken.None, TaskCreationOptions.None, sta);

//...

for(int i=0; i<10; i++)
{
    var result = await Task.Factory.StartNew(() =>
    {
        // use COM object
        return comObjects.Obj.Method();    
    }, CancellationToken.None, TaskCreationOptions.None, sta);
}

If Obj.Method() returns another COM objects, you should keep the result in the same StaTaskScheduler's "apartment" and access it from there, too:

var comObjects = new { Obj = (ComObject)null, Obj2 = (AnotherComObject)null };
//...
await Task.Factory.StartNew(() =>
{
    // use COM object
    comObjects.Obj2 = comObjects.Obj.Method();    
}, CancellationToken.None, TaskCreationOptions.None, sta);

If you also need to handle events sourced by Obj, check this:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!