Disabling control variable while worker thread is finishing MFC - c++

I am working on a dialog-based MFC Application using Visual Studio 2015. Basically my problem is that I have a button that will start a worker thread after the user has chosen the necessary inputs (.csv files that will be parsed and put into different vectors). To avoid complications, I decided that the user will not be able to press this button or the input buttons until after the calculation done by the worker thread has finished. I tried the WaitforSingleObject options but defeats the purpose of keeping the main thread or the MFC Application running while waiting for the worker thread to finish. Is there any other workaround around this problem? I appreciate any help.

Your worker thread could post a completion message back to your UI thread. Your UI thread wouldn't need a special message loop in that case, instead your window procedure would then reenable the buttons when it receives that message.

You could use the MsgWaitForMultipleObjects function:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684242(v=vs.85).aspx
ATL uses it in AtlWaitWithMessageLoop(https://msdn.microsoft.com/en-us/library/26hwk2bx.aspx).

Related

How to Run an event while another event is running in wxWidgets GUI?

I created one GUI having two buttons. one is start button and the other is stop button. when start is pressed the program will execute in the background and the gui will freeze. I couldn't control the window anymore. even a mouse click is not responding. the stop button is for stopping the program. since the window is not responding as it is running the program i cant press stop. what is the possible solution? .please help
A thread is sort of a subprogram inside your program. When the application starts it runs in the main thread. You can create many other threads; all of them (the main one included) share the application memory space (for example, same global vars in scope).
There are two kind of threads: "detached" and "joinable". detached threads delete themselves when they finish, think of them as "fire and forget". Conversely, joinable threads are deleted by yourself, only after they have completed their job.
In wxWidgets all GUI is executed in the main thread. Calling a GUI function from another thread is a nightmare, don't do it.
Your case is a typical situation. The "start" button launches a thread to do some job. If you want to cancel this job you push the "stop" button.
How to instruct the thread to cancel its job?
While you can use wxCondition, you can also set a flag on your own. The working thread reads at some moment this flag (it's not automagic, you must code it) and stops or continue depending on its value. Don't forget to use a wxMutex before accesing the flag to protect it from another thread changing it at the same time.
Also, threads can post messages to the main thread event-loop. This way you can tell the main thread that your worker thread has finished its job.
Threads require more attention when you're coding them. You must avoid some situations such as:
"dead lock": two threads wait one for each other, none finishes.
"race condition": several threads try to change a shared value at the same
time.
More on wxWidgets docs and thread sample.
Finally, C++11 has std::thread and other related friends (mutexes, semaphores, etc). It's your choice to use it instead of wxWidgets classes.

MFC - Getting device context of a specific window

I am new to MFC and trying to understand MFC's device context and UI threads.
I have created a UI Thread which opens a window. (I created a dialog class and i have called the doModal() in the thread's InitInstance.
And now from this UI thread i am creating one more WORKER thread.
I want to access the window opened by the UI thread from the worker thread.
Please suggest me how i could do that. I searched a lot over internet and i did'nt get proper answer.
You can't mess with UI objects from the worker thread. The best thing to do in this case is do whatever you need in the worker thread and once aresult is available inform the UI thread. This can be done with a CWnd.PostMessage with a costom WM_...
The UI thread has to handle this message and do the required UI handling.

MS Visual C++ Starting a function by clicking a button without blocking a dialog

I've created a dialog based MFC application on MS Visual Studio 2013. To the dialog, I've added ActiveX elements and some other list elements to show text output. One of the buttons with the ID IDC_BUTTONLAUNCH calls a function like
void CpiezcamDlg::OnBnClickedButtonlaunch()
{
SweepAndImage();
}
The function SweepAndImage(), which is a member of the class CpiezcamDlg and a bit more expensive (it takes about 10 sec). The function also calls updates to the list elements. There is also a Sleep function inside of SweepAndImage(). The result is that during the call of this function, the complete dialog is "blocked" and doesn't react (which makes sense). I've just started with MFC this week so my knowledge is rather limited. I tried to do
void CpiezcamDlg::OnBnClickedButtonlaunch()
{
#pragma omp parallel
{
#pragma omp single nowait
SweepAndImage();
}
}
to sort of "fork" the function into another thread. Since there's an implicit barrier at the end of the omp pragma, this doesn't work. I guess I need some sort event handler that is running in the background of my application and see if that button was clicked. Any kind of help or link is appreciated. If more information is needed, I'll add it.
OpenMP uses fork and thread to do work. It will not really do what you wish here.
MFC's GUI is running on the main thread. SweepAndImage will be run in a separate thread however OnBnClickedButtonlaunch will block waiting for SweepAndImage to return from doing work and then it will continue on. Because the main thread has been blocked updates to the GUI will also halt. Windows/MFC has a hidden window message pump that is abstracted away. That pump relies on event handlers (ie. your button press method) not blocking for too long so that the pump can continue on with the next event in the queue.
Since you are using MFC, MFC does have support for multithreading. I would recommend starting with this MSDN article
What you can do is create a new thread (see the article above) in your button handler that spawns off some work. That will allow the main thread to continue immediately and continue processing windows events in its pump.
To be complete:
Define
UINT SweepAndImage(LPVOID pParam)
Call it like
AfxBeginThread(SweepAndImage, NULL);
Instead of return 0, use
AfxEndThread(0, TRUE); /* or (1, ...) for return 1 */
to exit SweepAndImage

safely exit program Win32 C++ from detached std::thread

I have a simply utility that has GUI merely to provide progress and respond to mouse clicks for a button, in win main I've used std::thread and .detach to allow my worker thread to do the job without interrupting GUI. It works great, However I am wondering best method to safely end application (Note: I am Using Visual Studio 2013)
As far as I can tell there is no way to trigger an action on thread completion to exit the application , like .NET BackGroundWorker.
You can hold the handle to the main window (HWND) in your thread and post WM_QUIT message from your thread to the main UI thread.
You can use PostMessage or PostThreadMessage functions.

How do I create Modal dialog in worker thread(Non-UI thread)?

I have written a sample MFC application in which there are two threads:
-Main thread ( UI thread)
-Worker thread ( non-UI thread)
I have a specific requirement to create a Modal dialog in Non-UI ( worker thread).
When I create the CDialog object and call DoModal on the same, it works. The dialog gets created and acts as Modal to the application. ( Win XP SP2 machine) But this does not work in Windows 2003 server machine.
The behavior in 2003 server is that, the Modal Dialog goes behind the application main Window and dialog will be brought to front only when I click on Main Window. It is not acting as Modal dialog to my application.
What could be the problem -- any ideas?
If creating UI controls in non-UI thread is the issue then is there any Win32 API which will allow me to link my worker thread to Main UI thread such that DoModal happens in Main thread. I tried AttachThreadInput but it is not working.
There is no reliable way to spread GUI modality across multiple threads. Every window is represented by an object referenced through a HWND which in turn has thread affinity. This is a left-over from the 16-bit days of Windows, where there was no multi threading. Consequently the HWNDs are not protected against concurrent access. The Old New Thing has an excellent series on "Thread affinity of user interface objects" (Part 1 2 3 Addendum).
Modality is implemented by first enabling the dialog window and then disabling its parent. The first step is safe while the second attempts to disable a window from a thread which is not the window's owning thread. Since en-/disabling windows modifies the object referenced through the HWND it represents a race condition.
The suggested solution is to confine your GUI to a single thread and communicate from your worker thread to the GUI thread to have it perform user interaction on the worker thread's behalf. The easiest way to accomplish this is to call SendMessage from the worker thread to block until the GUI thread's message handler returns. If the worker thread should continue to run while the dialog is displayed you could use PostMessage instead and communicate back to the worker thread using PostThreadMessage or signaling a synchronization object like an Event Object.
First of all, I'd like to agree with other posters that it's probably better to show the dialog on the main UI thread.
However, if you must, you can make a dialog on another thread modal with the following steps:
Pass your active window as an owner when creating the dialog.
When dialog is showing, iterate over your other windows and do them EnableWindow(FALSE). When the dialog is hiding, do the reverse. You will probably have to remember windows' enabled state and restore the original state, not just EnableWindow(TRUE).
Ensure that accelerators and other global commands will be ignored while the dialog is shown.
Note that (2) shouldn't be necessary provided that you do (1), but you've mentioned MFC, and I don't remember exactly how it behaves. It has it's own modal dialog implementation which may not exactly match Win32. If you're lucky, (1) and (3) will be enough.
While i don't know about the specifics of dialog handling on Server 2003, the simplest workaround to get on the main thread would be to use a custom window message, do ::SendMessage() and display the dialog in the message handler.
I recommend you not to do what the question subject suggests, and confine all UI to one thread. If you need the other thread to communicate with the user, create some messaging mechanism that will ask the UI thread to do it, and transport the results back.