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.
Related
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).
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
I would like to use a ppl task to do some work in the background, and, upon completion, show the result in a window. In my case the UI-framework is MFC. The structure would be:
using namespace concurrency;
create_task([] {
// this can be run in any thread, shouldn't be the UI thread
// do real work here
return 42;
}).then([](int n)
{
// this should be run on the UI thread
// ... open a MFC window to display results
});
The thing is, a non Windows Store app doesn't allow to specify the task_continuation_context. Instead, the runtime decides which context will be used (see task_continuation_context Class).
Can I rely on the runtime to reliably figure out that it needs to run the continuation on the UI thread? Is there a reasonable workaround to achieve what I want - without blocking the UI thread?
Update: Playing around showed that the runtime will not run the continuation on the UI thread. So, is it impossible?
What I did to solve this was to create a Dispatcher class and a message-only window, which is a member of the Dispatcher. The Dispatcher must be constructed (I used a singleton) from the main thread such that the main thread takes care of the messages which are sent to the message-only window. I can pass a std::function to my Dispatcher::ExecuteInMainThread function. The Dispatcher will then invoke SendMessage on the message-only window, passing in the pointer (unfortunately only a pointer will be possible) to the std::function. The only message handler I need in the message-only window will then invoke the function I passed in - within the main thread.
This Dispatcher can be used in the task continuation to execute a std::function in the main thread.
I'm writing a console multi-process application in c++ using WinAPI. So I have the Dispatcher(e.g. "Parent") and the Client(e.g. "Child") processes. Both processes are synchronized: they're using semaphors, events, mutexes and the pipe (all of them are standard WinAPI handles). Application stop when the user type the "exit" command. If the user do so, the dispatcher process notifies it's child, and then child releases its resources and makes another before-exit procedures to exit correctly. But there's a thing that bothers me: what will happen if the user press the window "close" button? If so, I should listen to close event and then perform my resource-releasing procedure. What is the easiest way to handle window close event?
Write a console handler routine that detects CTRL_CLOSE_EVENT (and CTRL_C_EVENT, if desired), and use SetConsoleCtrlHandler to add the handler routine to your process.
It isn't really different from the client process crashing or being terminated through Task Manager. You ought to be resilient to that as well. The ultimate signal you get for that in the parent process is that the client's process handle will be signaled.
Use WaitForMultipleObjects, along with those other handles, to detect this.
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.