1

I'm writing plugin for one software. This software invokes

 void Init() {...}

on loading and have multithreading feature: program can run multiple threads and can call custom functions from my plugin at the same time.

In my plugin I'm using COM objects which I initialize following way:

void Init() { // "Global" initializaton
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    position.CreateInstance(__uuidof(Position));
    order.CreateInstance(__uuidof(Order));
}

And next I implement plugin-based function (example):

int SendOrder(....) {
    return order.SendOrder(...); // invoke COM object's method
}

Problem is that this variant not working as expected so I moved COM object instantiation directly to the function's body:

int SendOrder(....) {
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    order.CreateInstance(__uuidof(Order));

    int ret = order.SendOrder(...);

    CoUnitialize();

    return ret;
}

Now COM object will be instantiated on every function call and this variant works as expected (every thread now have it's own apartment and object's instance), but I'm afraid that is not the best solution, because instantiation is costly operation.

Can this be done somehow better?

4
  • I'm not sure what you're asking. What are you trying to achieve? Is it okay for the application to execute SendOrder from multiple threads at the same time? What isn't working as expected? Commented Oct 26, 2013 at 21:39
  • @dauphic I want to avoid COM object instantiation on every function's call. If it possible, of course. I'm novice in COM. Commented Oct 26, 2013 at 21:41
  • So when you create your order in Init, what is the problem you're seeing? Commented Oct 26, 2013 at 21:46
  • @dauphic order.SendOrder do nothing when I call int SendOrder(....) repeatedly in cycle (but works if I call it at once). I don't know, STIOrder class is thread-safe or not, because this COM library from different supplier. Commented Oct 26, 2013 at 21:50

1 Answer 1

1

If you want to be able to invoke COM objects at the same time on multiple threads, you should be initializing the the thread to use a multi-threaded apartment, instead of single-threaded apartment.

Currently, you're initializing the thread as a single-threaded apartment, which means that any objects created on that thread will only execute their functions on that thread. If you attempt to use one of these objects from a different thread, the calls will be marshaled to the thread that created them.

If COM needs to marshal a function call to another thread, it does it via Windows's messaging system. If the thread isn't pumping it's messages, the function will never be called; this is most likely what's happening to you, and why you're seeing that nothing gets executed.

If you initialize your thread as a multi-threaded apartment by using COINIT_MULTITHREADED instead of COINIT_APARTMENTTHREADED when you call CoInitializeEx, it will allow objects created by this thread (i.e. your order) to be used on any other thread.

Sign up to request clarification or add additional context in comments.

5 Comments

I tried to initialize COM with COINIT_MULTITHREADED in void Init() but it always fails. Probably this COM library can run only in STA mode...
What does CoInitializeEx return? Or does it fall later?
CoInitializeEx(NULL, COINIT_MULTITHREADED) returns RPC_E_CHANGED_MODE. A-ha, this not fail, but I'm anyway have troubles with order.SendOrder...
This means that something on this thread has already called CoInitializeEx. You have to find that and change it, or create a new thread to initialize your objects on.
Alternatively, if this isn't possible, you can pump messages on the thread that calls Init so other threads can marshal to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.