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?
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.
Related
We have a code that registers a callback. So the flow that registers the callback has no knowledge of when the callback will be called.
Now the callback will called by another flow in a thread - hence the main flow that has registered the callback needs to wait for callback to complete.
I am having no idea to implement the same as I cannot modify anything in the other thread that will call the callback. How can I make my main thread to responds synchronously - after the callback is called by other thread?
You will need to share some state between the two that can be used to communicate this.
As a corollary, if the callback is stateless, this cannot be done (or only within certain restrictions, such as limiting the number of callbacks that can be active at the same time).
Since the access to that shared state potentially happens concurrently from different threads, all access needs to be synchronized, ie. made thread-safe.
Here is a simple example using std::future:
#include <future>
// [...]
std::promise<void> p;
do_work_async([&p]() { p.set_value(); });
std::future<void> f = p.get_future();
f.get(); // this line will block until the callback is executed
Note that this has potential lifetime issues: The promise needs to be kept alive until the callback has executed. Depending on your program, this might make it necessary to put the promise on the heap.
If stateless callbacks are not supported (eg. the callback parameter must be a plain C-function pointer and no injection point for user state is provided) you need to put your shared state into static storage instead, with the usual resulting limitations.
i have a .NET application which is using a COM component using COM Interop, The Component instanciate itself and interface pointer is returned in an API cal to the .net wrapper, at a later point in the application flow a call is made to the COM component.
//Pseudo code
//CLISD_ITEM is a another CoClass housed by this COM component, the component is a STA based dll
HRESULT GetItem(ITem **ptr)
{
HRESULT hr = CoCreateInstance(CLSID_ITEM.....,....(void **) &pItem);
pItem->QI(ptr);
}
my question is should i call CoInitialize and CoUninitialize() inside the function GetItem, as of now i not making these calls and the code seems to be working fine, but there are reports of some intermittent crash when calling CoCreateInstance.
if anyone can help me here.
No, CoInitializeEx() must always be called by the owner of the thread. Which is never the component itself, it didn't start the thread. Only the owner can determine which apartment type is correct since it needs to take care of apartment guarantees. In particular, an STA thread must pump a message loop. A component can never provide that guarantee.
And this is done consistently in a .NET app, the CLR always calls CoInitializeEx() before it allows any managed code to run on the thread. The apartment type is selected by the [STAThread] or [MTAThread] on the Main() entrypoint for the startup thread, the Thread.SetApartmentState() call for a worker thread. Threadpool threads always join the MTA.
You'll need to look for another reason for the crash.
Provided you're using this from a thread marked STA with SetApartmentState within .NET, you shouldn't need to do this.
If you're calling this directly on a UI thread (ie: the main Windows Forms or WPF thread) this will be done for you already.
Some time ago, I had to modify an old COM DLL (Visual C++ 2010, ATL) migrating it from "Apartment" threading model to "Both", i.e. it can now be called from both STA and MTA threads without serializing calls (of course, I had to add internal synchronization for shared data). This in turn caused problems when translating COM events (connection points) to .NET events when my DLL is called via Interop from a .NET application (I must support both STA and MTA even in .NET applications).
To tackle these problems, I changed the way events are fired.
1) If the DLL is called in a STA context, it works like before, i.e. it creates an invisible window, then, when the event must be raised, it calls PostMessage to that window, then the main STA thread calls the actual event-firing code, i.e. CProxy_IMyEventFiringInterface member functions (CProxy_IMyEventFiringInterface derives from IConnectionPointImpl).
2) if the DLL is called in a MTA context, I don't have a main COM thread and I cannot do PostMessage, so I use a custom thread I create and let that thread call IConnectionPointImpl functions.
But AFAIK there is no Windows API that detects if the calling thread is STA or MTA. Many websites suggest to use CoInitializeEx like this:
HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
switch(hr)
{
case S_FALSE: // we are in a Multi-Threaded Apartment (MTA)
CoUninitialize(); // each successful call to CoInitialize or CoInitializeEx, including any call that returns S_FALSE, must be balanced by a corresponding call to CoUninitialize
break;
case RPC_E_CHANGED_MODE: // we are in a Single-Threaded Apartment (STA)
break;
default: // IMPOSSIBLE!!!!
}
I decided to put this call to CoInitializeEx in CMyComComponent::FinalConstruct.
Everything worked fine... till today. In a customer scenario, I see from my tracing tool that for a certain .NET EXE application (I do not have the source code) the above code ends up in the default branch because CoInitializeEx returned S_OK.
How can this be possible? Microsoft documentation says that S_OK means "The COM library was initialized successfully on this thread", but I am INSIDE a COM object, the COM library MUST be already initalized!
By the way, the default branch does not shut down the application, but, since S_OK was returned, it called CoUninitialize (each successful call to CoInitialize or CoInitializeEx, including any call that returns S_FALSE, must be balanced by a corresponding call to CoUninitialize) and then the DLL goes on assuming STA (a wrong move in hindsight). But it's not STA: in fact, a later PostMessage returns FALSE.
I can simply change the code to use MTA as the default if CoInitializeEx(NULL, COINIT_MULTITHREADED) returns S_OK, I should have done it right from the start.
But I also want to be SURE that this is the right thing to do, to avoid further problems in the future.
Thank you very much
Demetrio
This is possible when you are on implicit MTA thread. The correct function is like this:
BOOL IsMultiThreadedApartment() throw()
{
HRESULT nResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(SUCCEEDED(nResult))
CoUninitialize();
return SUCCEEDED(nResult);
}
You are hitting this unusual situation because the caller application failed to initialize COM on the thread it instantiates your class on. However be aware that if later the caller initializes the thread as STA, you might get into tricky situation having your class running in MTA mode on STA thread. Doing CoInitializeEx yourself on the other hand might cause failure of the caller to do erroneously late COM initialization.
i have an encoder class with lots of methods . this is a subclass of Qthread. i am new to multi-threading and
trying to understand how this class is
threading its methods
... i understand to thread a method it has to be in a subclass of qthread. and the run of this implements the threaded code for this class. And the thread starts only when a call to start method on the object of this class is made.
Question : firstly what do you infer
from the this run implementation
void Encoder::run(void)
{
VERBOSE(VB_DEBUG, "Encoder::run");
if (WILL_PRINT(VB_DEBUG))
print_stats_timer_id = QObject::startTimer(kEncoderDebugInterval);
health_check_timer_id = QObject::startTimer(kEncoderHealthCheckInterval);
if (init())
exec();
else
VERBOSE(VB_ERROR, "Encoder::run -- failed to initialize encoder");
QObject::killTimer(health_check_timer_id);
if (print_stats_timer_id)
QObject::killTimer(print_stats_timer_id);
cleanup();
}
Question: what does thread context mean in
relation to its methods .
also
Question: what would happen If a method of this
class is called before this class's
thread has started
The class you have written creates a thread and initializes a QObject::timer. It then goes on to call a user defined init() function then the QThread::exec() function.
My guess is that you intended that exec() would be a user defined function where the actual work is to occur. Be aware that QThread::exec() processes the thread's Qt Event Queue.
Also, on some platforms you may get an "Error creating timer from thread" warning message. I've encountered this error on Windows when the code executed fine on Linux
Also, be aware that your timer will never occur if you do not call the QThread::exec() function or QApplication::processEvents() from within your thread.
Thread context in Qt is the same as any other thread concept. That is, all memory is shared between the threaded code (entered at this point in your "run()" function). And any other context which calls into your object. If this object may ever be executing in a thread and accessed from outside of the thread you must protect the shared data.
Because all data is shared between thread contexts (it's a shared memory multiprocessing model) there is no problem with calling functions before/after/during thread execution. Given that:
The object is fully constructed before you call any method. This is not special to threads, necessarily, unless the object is created in a thread.
Any data member is protected with a mutex lock (I eluded to this in #2). QMutexLocker is a handy stack based RAII way of dealing with mutex locks in Qt.
I believe I fully answered your question here, so I'll go ahead and link to RAII and threading articles I have written on another site, just for further reference.
Edit: specificity about threading scenarios:
class MyThreadedClass : public QThread
{
MyThreadClass(const boost::shared_ptr<SomeOtherClass> &t_object)
: m_object(t_object) {}
void doSomething()
{
// Depending on how this method was called (from main, from internal thread)
// will determine which thread this runs on, potentially complicating thread
// safety issues.
m_object->someThing();
}
void run()
{
// I'm now in a thread!
m_object->someFunction(); // oops! The call to someFunction is occurring from
// a thread, this means that SomeOtherClass must be
// threadsafe with mutex guards around shared
// (object level) data.
// do some other stuff
}
};
int main()
{
MyThreadClass thread(someobjectfromsomewhere);
thread.start(); // MyThreadClass is now running
thread.doSomething(); // The call to doSomething occurs from main's thread.
// This means 2 threads are using "thread", main
// and "thread"'s thread.
// The call to thread.doSomething hits Thread.m_object, which means that
// now multiple threads are also accessing m_object ("thread" and "main").
// This can all get very messy very quickly. It's best to tightly control
// how many threads are hitting an object, and how
}
NOTE: It would be a good idea to investigate QFuture, which is designed to handle this kind of asynchronous task, like an encoder, that you are looking at QFuture will avoid some of the potential threading issues of shared data and deadlocks.
I have created an in-process COM object (DLL) using ATL. Note that this is an object and not a control (so has no window or user-interface.) My problem is that I am trying to fire an event from a second thread and I am getting a 'Catastrophic failure' (0x8000FFFF). If I fire the event from my main thread, then I don't get the error. The second thread is calling CoInitializeEx but this makes no difference. I am using the Apartment threading model but switching to Free Threaded doesn't help.
The fact I am trying to do this from a second thread is obviously crucial. Is there an easy way to do this or am I going to have to implement some hidden-window form of messaging?
For example, in my main object's source file:
STDMETHODIMP MyObject::SomeMethod(...)
{
CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
// Succeeds with S_OK
FireEvent(L"Hello, world!");
return S_OK;
}
DWORD WINAPI ThreadProc(LPVOID param)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
MyObject* comObject = reinterpret_cast<MyObject*>(param);
// Fails with 0x8000FFFF
comObject->FireEvent(L"Hello, world!");
}
void MyObject::FireEvent(BSTR str)
{
...
// Returns 0x8000FFFF if called from ThreadProc
// Returns S_OK if called from SomeMethod
pConnection->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, NULL, NULL);
}
COM basics
In STA your object lives on a single thread (The Thread). This thread is the one it's created on, it's methods are executed on and it's events are fire on. The STA makes sure that no two methods of your object are executed simultaneously (because they have to be executed on The Thread so this is a nice consequence).
This does not mean that your object can't be accessed from other threads. This is done by creating proxies of your object for every thread other than The Thread. On The Thread you pack an IUnknown with CoMarshalInterThreadInterfaceInStream and on the other thread you unpack with CoGetInterfaceAndReleaseStream which actually creates the proxy on the other thread. This proxy uses the message pump to sync calls to you object, calls that are still executed on The Thread, so The Thread has to be free (not busy) to executed a call from another thread.
In your case you want your object to be able to execute methods on one thread and rise events on another thread. So this has to happen in MTA, so your object has to live in MTA, so your class has to be free-threaded. Threads belong to exactly one apartment, so a thread can not be in MTA and STA simultaneously. If your object lives in MTA whenever an STA object tries to use it, it will have to create a proxy. So you get a slight overhead.
What I guess is that you are thinking of some very clever "technique" to offload your main thread, and do some "async" events, which will not fly in the end :-)) If you think about it there has to a listener on this second [worker] thread...
Btw, this line
MyObject* comObject = reinterpret_cast<MyObject*>(param);
can be done in MTA only.
I think the real problem is not what your component is configured with, but the host process. Many hosts, like the Office Object Model ones, live in a single threaded apartment in which case it is not allowed to call them from anything but the main thread.
If that is the case you can let COM do the work by using the single threaded apartment model and moving the actual call to a function in a CoClass and invoke that function from your thread.
That only passes window messages behind the scenes as well, but spares you from implementing this yourself.
Threading in COM (wikipedia):
The Single-Threaded Apartment (STA) model is a very commonly used model. Here, a COM object stands in a position similar to a desktop application's user interface. In an STA model, a single thread is dedicated to drive an object's methods, i.e. a single thread is always used to execute the methods of the object. In such an arrangement, method calls from threads outside of the apartment are marshalled and automatically queued by the system (via a standard Windows message queue). Thus, there is no worry about race conditions or lack of synchronicity because each method call of an object is always executed to completion before another is invoked.
See also Message Pumping in the same article.