I am having a problem with using GetDlgGetItemText inside a worker thread. it is working perfectly fine outside with
TCHAR txtbuff[50];
GetDlgItemText(IDC_SLIDER1, txtbuff, 50);
SOmething = ::SendMessage(something,WM_SETTEXT,0,(LPARAM)txtbuff)
but when i try to use the same in a worker thread I get told that it doesn't take 3 arguments, because it needs it's HWND handle (from what I have gathered), which I thought was gained using winspy++ or similar, but those handles change all the time. I thought (quite wrongly because I am new to this) that I could simply use the same code inside my worker thread. how come the above code works fine outside of the worker thread? I have looked around everywhere, am I missing something blatantly obvious/simple?
The GetDlgItemText version that needs only 3 arguments is a CWnd member function. MFC translates it into the 4-argument API version using the m_hWnd member of the CWnd. So you cannot use the 3 argument version outside of a CWnd object.
Another problem is that both versions of GetDlgItemText are defined to work only for accessing child windows. So you cannot use them unless calling in the context of the parent window of the IDC_SLIDER1 control.
And another problem is that MFC does not support accessing a window/control from a thread that did not create the window. There are some limited cases where this works but it is poor practice. Even when it works it causes unobvious interactions between the threads, possibly leading to a deadlock.
Put all of your interactions with the GUI into the main thread. And put all your interactions with child windows (i.e. controls) in the parent window class.
Related
When I create a new thread in a program... in it's thread handle function, why do I pass variables that I want that thread to use through the thread function prototype as parameters (as a void pointer)? Since threads share the same memory segments (except for stack) as the main program, shouldn't I be able to just use the variables directly instead of passing parameters from main program to new thread?
Well, yes, you could use the variables directly. Maybe. Assuming that they aren't changed by some other thread before your thread starts running.
Also, a big part of passing parameters to functions (including thread functions) is to limit the amount of information the called function has to know about the outside world. If you pass the thread function everything it needs in order to do its work, then you can change the rest of the program with relative impunity and the thread will still continue to work. If, however, you force the thread to know that there is a global list of strings called MyStringList, then you can't change that global list without also affecting the thread.
Information hiding. Encapsulation. Separation of concerns. Etc.
You cannot pass parameters to a thread function in any kind of normal register/stack manner because thread functions are not called by the creating thread - they are given execution directly by the underlying OS and the API's that do this copy a fixed number of parameters, (usually only one void pointer), to the new and different stack of the new thread.
As Jim says, failure to understand this mechanism often results in disaster. There are numnerous questions on SO where the vars that devs. hope would be used by a new thread are RAII'd away before the new thread even starts.
I am developing an UI application that creates a COM object along the way.
The problem is, I want to "move" this COM object entirely on a different thread.
What I do is this:
create the new thread I want to move the object into (with CreateThread API)
after entering this thread, I'm calling PeekMessage to setup a message queue for it
calling CoInitialize, CoCreateInstance to create the COM object, QueryInterface to get the interface I want
finally I call a method on the interface that displays a MessageBox with the value returned by GetCurrentThreadId() (I have access to the VB6 code of the COM library within which the object resides).
The problem is, as this message box shows, the object methods are still executed on the original UI thread, not on the thread I created and done all those steps into. One more thing to mention, after calling the interface method, I'm also setting up a classic message loop in it.
How can I change this behaviour and achieve what I want? (that is, I want the COM object calls that originate from my newly created thread to be executed ON IT, not on the original application thread)
Here's some pseudocode to make it even more clearer:
void myMainUIMethod(){
MessageBox(GetCurrentThreadId()); // displays 1
CreateThread(&myCOMObjectThreadProc);
}
void myCOMObjectThreadProc(){
MessageBox(GetCurrentThreadId()); // displays 2
CoInitialize(NULL);
myObject = CoCreateInstance(myObjectsCLSID);
myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
myObjectInterface->showThreadIDMessageBox(); // this would be the COM object method call
}
And, in the VB6 code of the object, here's the pseudo-definition of showThreadIDMessageBox.
Public Sub showThreadIDMessageBox()
Call MessageBox(GetCurrentThreadId()) //displays 1, I want it to display 2
End Sub
I have achieved what I wanted by CoUninitalizing on the main thread, before creating the new thread. But why does this happen? If COM was initialized ON THE MAIN THREAD before I'm creating the new thread, maybe for some reason it had to be..I would't want the application to crash later because I had to call CoUninitialize before creating my new thread. Here's some pseudocode that illustrates that whichever thread calls CoInitialize first will be the one picked by the STA objects.
void myMainUIMethod(){
MessageBox(GetCurrentThreadId()); // displays 1
CoUninitialize(); // uninitialize COM on the main thread
CreateThread(&myCOMObjectThreadProc);
***i: MessageBox("When you want to initialize COM on main thread, confirm this");
CoInitialize();
}
void myCOMObjectThreadProc(){
MessageBox(GetCurrentThreadId()); // displays 2
***ii: MessageBox("When you want to initialize COM on the new thread, confirm this");
CoInitialize(NULL);
myObject = CoCreateInstance(myObjectsCLSID);
myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
myObjectInterface->showThreadIDMessageBox(); // this shows 2 IF ***ii is confirmed before ***i, 1 otherwise
}
Thank you very much in advance,
Corneliu
Looks like your problem is that your COM component threading model is not specified in registry key InprocServer32. This means that object is considered as STA (single-threaded apartment) but will be loaded to main (or host) STA, not the STA that created it. This is the first thread that called CoInitialize. To be created in same STA that called CoCreateInstance you must create HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{Your CLSID}\InprocServer32#ThreadingModel registry value and set it to Apartment.
Quote from MSDN (InprocServer32 registry key documentation):
If ThreadingModel is not present or is not set to a value, the server is loaded into the first apartment that was initialized in the process. This apartment is sometimes referred to as the main single-threaded apartment (STA). If the first STA in a process is initialized by COM, rather than by an explicit call to CoInitialize or CoInitializeEx, it is called the host STA. For example, COM creates a host STA if an in-process server to be loaded requires an STA but there is currently no STA in the process.
I have finally achieved what I wanted! Adding a CoUninitialize call in the main UI thread, before creating the new thread has solved it. This happens because STA COM objects will be handled on the thread that first calls CoInitialize. Now all the calls to the objects methods are reported to be executed on the thread I created and the main window of the object (the COM component has a Form) is reported to belong to it too! (used WinSpy++ to test that).
There is still a question (and a problem) though..why does it behave this way?
Everywhere I search on the internet I see answers telling that a STA COM component will be fully executed on the thread it is created on (provided that CoInitialize or CoInitializeEx with COINIT_APARTMENTTHREADED had been called before), no matter what. Why does it matter if I called CoInitialize on another thread before..that's just plain stupid in my opinion for Microsoft to do so :), plus it might damage the future behaviour of my application, as I stated before.
EDIT: The correct answer is the one posted by Frost. Thank you again.
The threads are running in parallel and that's what they are meant to do. you need to synchronize between the two threads if you want one object to wait for some operation on other thread to complete. Event object will serve for your purpose.
You need to choose Free Threading as the Threading Model of the COM class when creating it. With C++ ATL, this is an option in the wizard when you select New -> COM class (or something like it). In .NET languages, I think this is specified as an attribute in the class.
BTW, you don't need to call QueryInterface after CoCreateInstance (unless you need more than one interface pointer). Just pass the GUID of the interface you want as the 4th parameter to CoCreateInstance.
Ah, I think I might know the problem now: it sounds like the VB6 COM object you are creating was registered as single-threaded, not apartment-threaded; this means that the object gets created on whichever thread is your app is the first to call CoInitialize().
This explain the behavior you are seeing: if you let your main thread CoInitialize() first, it becomes the "main thread" as far as COM is concerned, so the CoCreate ends up creating the object on it, even though it's CoCreated on a different thread. (This is only the case for single-threaded objects.)
But when you let your other thread CoInitialize() first, it is the "main thread" for COM, so the object gets created where you want it.
Can you change the threading model of your VB object to apartment instead of single? This would enable it to get created on the thread that calls CoCreate().
The problem is, I cannot change the threading model of the VB6 component since it is already used in other applications and it might damage it's behaviour.
...looks like that won't work for you. I guess you can check what the current threading model is, and if you can confirm that it's single, then you'll have an explanation for why it behaves the way it does, which might help you work with it.
--
So why does COM behave that way? - A: legacy compat issues. The Single Thread model is a holdover from before windows had threads in the first place, when every process had just one thread, and code didn't have to make any assumptions about synchronizations between objects within a process. To preserve this illusion and allow objects that were written assuming single-threaded COM to be used in a multithreaded environment, COM introduced the 'single' model, also known as 'legacy STA'. More details on this page, scroll down or search for "Legacy STA" for the details. COM basically puts all of these 'single' objects on the same [STA] thread - and uses whichever thread just happens to be the first to call CoInitialize. When you CoUninit and CoInit again on another thread, you're essentially restarting COM; so it's now the second thread that is the new "first thread to call CoInit", so that's why COM then ends up using that one...
(Legacy STA is such an old issue is was actually hard to track down any details; nearly all other articles mention apartment, free and both options; but there's rarely details about 'single'.)
I'm working on a project where I need to make a program run on multiple threads. However, I'm running into a bit of an issue.
In my program, I have an accessory function called 'func_call'.
If I use this in my code:
func_call((void*) &my_pixels);
The program runs fine.
However, if I try to create a thread, and then run the function on that, the program runs into a segmentation fault.
pthread_t thread;
pthread_create (&thread, NULL, (void*)&func_call, (void*) &my_pixels);
I've included pthread.h in my program. Any ideas what might be wrong?
You are not handling data in a thread safe manner:
the thread copies data from the thread argument, which is a pointer to the main thread's my_pixels variable; the main thread may exit, making my_pixles invalid.
the thread uses scene, main thread calls free_scene() on it, which I imagine makes it invalid
the thread calls printf(), the main thread closes stdout (kind of unusual itself)
the thread updates the picture array, the main thread accesses picture to output data from it
It looks like you should just wait for the thread to finish its work after creating it - call pthread_join() to do that.
For a single thread, that would seem to be pointless (you've just turned a multi-threaded program into a single threaded program). But on the basis of code that's commented out, it looks like you're planning to start up several threads that work on chunks of the data. So, when you get to the point of trying that again, make sure you join all the threads you start. As long as the threads don't modify the same data, it'll work. Note that you'll need to use separate my_pixels instances for each thread (make an array of them, just like you did with pthreads), or some threads will likely get parameters that are intended for a different thread.
Without knowing what func_call does, it is difficult to give you an answer. Nevertheless, here are few possibilities
Does func_call use some sort of a global state - check if that is initialized properly from within the thread. The order of execution of threads is not always the same for every execution
Not knowing your operating system (AIX /Linux/Solaris etc) it is difficult to answer this, but please check your compilation options
Please provide the signal trapped and atleast a few lines of the stack-trace - for all the threads. One thing you can check for yourself is to print the threads' stack-track (using threads/thread or pthread and thread current <x> based on the debugger) and and if there is a common data that is being accessed. It is most likely that the segfault occurred when two threads were trying to read off the other's (uncommitted) change
Hope that helps.
Edit:
After checking your code, I think the problem is the global picture array. You seem to be modifying that in the thread function without any guards. You loop using px and py and all the threads will have the same px and py and will try to write into the picture array at the same time. Please try to modify your code to prevent multiple threads from stepping on each other's data modifications.
Is func_call a function, or a function pointer? If it's a function pointer, there is your problem: you took the address of a function pointer and then cast it.
People are guessing because you've provided only a fraction of the program, which mentions names like func_call with no declaration in scope.
Your compiler must be giving you diagnostics about this program, because you're passing a (void *) expression to a function pointer parameter.
Define your thread function in a way that is compatible with pthread_create, and then just call it without any casts.
According to http://doc.qt.io/qt-5/qpointer.html, QPointer is very useful. But I found it could be inefficient in the following context:
If I want to show label for three times or do something else, I have to use
if(label) label->show1();
if(label) label->show2();
if(label) label->show3();
instead of
if(label) { label->show1();label->show2();label->show3(); }
just because label might be destroyed in another thread after label->show1(); or label->show2();.
Is there a beautiful way other than three ifs to get the same functionality?
Another question is, when label is destroyed after if(label), is if(label) label->show1(); still wrong?
I don't have experience in multi-threaded programs. Any help is appreciated. ;)
I think the only safe way to do it is to make sure you only access your QWidgets from within the main/GUI thread (that is, the thread that is running Qt's event loop, inside QApplication::exec()).
If you have code that is running within a different thread, and that code wants the QLabels to be shown/hidden/whatever, then that code needs to create a QEvent object (or a subclass thereof) and call qApp->postEvent() to send that object to the main thread. Then when the Qt event loop picks up and handles that QEvent in the main thread, that is the point at which your code can safely do things to the QLabels.
Alternatively (and perhaps more simply), your thread's code could emit a cross-thread signal (as described here) and let Qt handle the event-posting internally. That might be better for your purpose.
Neither of your approaches is thread-safe. It's possible that your first thread will execute the if statement, then the other thread will delete your label, and then you will be inside of your if statement and crash.
Qt provides a number of thread synchronization constructs, you'll probably want to start with QMutex and learn more about thread-safety before you continue working on this program.
Using a mutex would make your function would look something like this:
mutex.lock();
label1->show();
label2->show();
label3->show();
mutex.unlock()
As long as your other thread is using locking that same mutex object then it will prevented from deleting your labels while you're showing them.
They seem to perform a reasonably similar task: launching a new thread that performs that selector quickly and easily. But are there any differences? Maybe with regards to memory management?
Both are identical.
In iOS and Mac OS X v10.5 and later, all objects have the ability to spawn a new thread and use it to execute one of their methods. The performSelectorInBackground:withObject: method creates a new detached thread and uses the specified method as the entry point for the new thread. For example, if you have some object (represented by the variable myObj) and that object has a method called doSomething that you want to run in a background thread, you could could use the following code to do that:
[myObj performSelectorInBackground:#selector(doSomething) withObject:nil];
The effect of calling this method is the same as if you called the detachNewThreadSelector:toTarget:withObject: method of NSThread with the current object, selector, and parameter object as parameters. The new thread is spawned immediately using the default configuration and begins running. Inside the selector, you must configure the thread just as you would any thread. For example, you would need to set up an autorelease pool (if you were not using garbage collection) and configure the thread’s run loop if you planned to use it. For information on how to configure new threads
I presume they are the same, as - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; is defined in NSThread.h in the NSObject (NSThreadPerformAdditions) category. That is nothing conclusive, but that is evidence in that direction.