Basically exactly what the title says. I would like to update the text that a button contains every 1 second when the user presses that particular button. I have noted that when the program doesn't have focus it works alright and the text refreshes correctly but when I am hovering over the program or when I am trying to click on it's menu Windows inform me that the program is unresponsive and asks me if I want it terminated. When the loop finishes the program returns to its normal state. Also any action I might have done (like moving it around or closing it) while it was Sleep()-ing is executed after the loop. Here is a bit of code:
case ID_BUTTON_START:
// Code executed when pressing Start Button.
char startButtonText[30]; // Storing next loop text
for (int i=5; i>0; i--)
{
sprintf(startButtonText, "Starting in ... %d", i);
SendMessage(hwndButtonStart, WM_SETTEXT, 0, (LPARAM)(startButtonText));
Sleep(1000);
}
Is this normal? If not what's causing this?
The WndProc does not process messages asynchronously within an application which means all messages are expected to be handled quickly and a return value delivered immediately. You must not Sleep in the UI thread since it will block other UI events from being processed. Any heavy work or synchronous requests/jobs which are likely to take a long time should be performed in worker threads. There are at least three viable options:
Create a new (worker thread) for the task.
If the task is likely to be done often, use a thread pool instead.
Set and subscribe to timer events.
I think the call to Sleep() might be keeping you from returning from the WndProc, so your application is not processing the incomming events for 5 secs. I suggest you try to subscribe to 5 timer events in 1s, 2s,..., 5s. Like when the timer message is recieved the button text must change. I don't know a way how to do that off the top of my head.
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've an application visual c++ written using vs2010,
I have two buttons: "start" and "stop",the first one calls a function that takes a lot of time to process, so in a certain moment I'd like to stop the computation pressing stop button. But in my application the button start seems still clicked (I think it's waiting for the return of the function) and all the other buttons appear to be disabled. Even if I had a wonderful stop function, I could not active because I'm not able to click on button stop. Solutions,ideas,using threads,easy example? Thanks.
You need to run your calculations in another thread. Otherwise your gui freezes until your calculations are done (because only one thing can be done at the moment).
If you are using some modern compiler look at std::thread.
other solutions are boost threads or even microsoft threads.
If your computation is a loop, it may be quite easy to check at each iteration if your User wants to stop the computation.
In the computation thread:
while(compute){
// one loop of computation
}
While your GUI thread can set computationto false through your stop button.
I hope it helps
Note: In c++ as in java Swing etc.., the GUI has it's own thread (not really visible to the developer) and you should never do heavy tasks in it. For instance, every callbacks for buttons should be as small as possible to keep your GUI responsive. This thread's job is just to drive your application.
Button 1 -> onClick =
{
start thread -> { do stuff here }
}
BUtton 2 -> onClick =
{
close thread
}
Be careful when forcibly closing a thread because you can leak memory !
http://msdn.microsoft.com/it-it/library/system.componentmodel.backgroundworker%28v=vs.110%29.aspx
BackgroundWorker is perfect for this use!
First you need to imports the namespace
using System.Threading;
then use the following code :
Thread T=new Thread(Your Code Goes method name);
your method name()
{
// your code goes here
}
T.Start();
then
T.Abort();
Basically exactly what the title says. I would like to update the text that a button contains every 1 second when the user presses that particular button. I have noted that when the program doesn't have focus it works alright and the text refreshes correctly but when I am hovering over the program or when I am trying to click on it's menu Windows inform me that the program is unresponsive and asks me if I want it terminated. When the loop finishes the program returns to its normal state. Also any action I might have done (like moving it around or closing it) while it was Sleep()-ing is executed after the loop. Here is a bit of code:
case ID_BUTTON_START:
// Code executed when pressing Start Button.
char startButtonText[30]; // Storing next loop text
for (int i=5; i>0; i--)
{
sprintf(startButtonText, "Starting in ... %d", i);
SendMessage(hwndButtonStart, WM_SETTEXT, 0, (LPARAM)(startButtonText));
Sleep(1000);
}
Is this normal? If not what's causing this?
The WndProc does not process messages asynchronously within an application which means all messages are expected to be handled quickly and a return value delivered immediately. You must not Sleep in the UI thread since it will block other UI events from being processed. Any heavy work or synchronous requests/jobs which are likely to take a long time should be performed in worker threads. There are at least three viable options:
Create a new (worker thread) for the task.
If the task is likely to be done often, use a thread pool instead.
Set and subscribe to timer events.
I think the call to Sleep() might be keeping you from returning from the WndProc, so your application is not processing the incomming events for 5 secs. I suggest you try to subscribe to 5 timer events in 1s, 2s,..., 5s. Like when the timer message is recieved the button text must change. I don't know a way how to do that off the top of my head.
I occasionally need to process a large amount of data from one package off the network, which takes sufficiently long that when the user tries to interact with the application windows adds the "(Not Responding)" string to the window title. I am aware this is because the processing is being done within a call to handle a message (some way up the stack) and therefore is blocking the message pump. I'm also aware the ideal way to deal with this is to process the data asynchronously in a separate thread so the pump can continue running, however this is a LARGE desktop application which is single threaded from top to toe and safely spinning this processing off is not feasible in our time frame.
So with that in mind, is there by any chance a way I can at least avoid the "not responding" moniker (which to most users reads as "has crashed") by telling windows my application is about to be busy before I begin the work? I believe there is something along these lines when responding to a request to close, one can keep asking windows for more time to avoid it proclaiming that your not "closing in a timely fashion"
I should add this is a C++ MFC application.
I don't think the Windows API can help you here.
Alternatively, how about showing a dialog box with a progress bar and make it run in a separate thread?
A text like "This operation may take half an hour" on the dialog box may be appropriate too.
Ok, firstly I upvoted Frederick's post because like it or not, the second thread is probably the best way to go.
However, if you really don't want to go down this road, you could manually pump the message queue within your apps inner loop. Something like this;
int Refresh()
{
MSG msg;
if (PeekMessage (&msg, NULL, 0, 0,PM_NOREMOVE))
if ((msg.message == WM_QUIT)
||(msg.message == WM_CLOSE)
||(msg.message == WM_DESTROY)
||(msg.message == WM_NCDESTROY)
||(msg.message == WM_HSCROLL)
||(msg.message == WM_VSCROLL)
)
return(1);
if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return(0);
}
This is actually a piece of code I used prior to rewriting something similar as a seperate thread. Basically I have a look at the queue, filter out unwanted messages, and post on the rest. It works to an extent, but caused some occasional nasty side effects, hence the rewrite.
You don't have to actually do anything with the messages from PeekMessage. Just call PeekMessage, you don't even have to remove anything from the queue or process it. As long as it is called every 5 seconds or so, it will cause windows to think the process is still responsive.
An alternative idea is to have a separate process/thread that will appear in the notification tray and inform the user that the process is busy waiting for an internal operation to complete. You'll see these in the later versions of Visual Studio, SQL Server Management Studio, etc.
Win32 has a method for this in user32.dll.
DisableProcessWindowsGhosting()
Disables the window ghosting feature for the calling GUI process. Window ghosting is a Windows Manager feature that lets the user minimize, move, or close the main window of an application that is not responding.
In addition to the above documented behavior, I also verified here (in a C# application) that this Win32 call also prevents the Not Responding label from appearing on the window as desired.
I found this via the C# answer to similar question here: https://stackoverflow.com/a/15380821/29152.
If you fork off a thread you're most likely worried about some other user action happening which may depend on the result of the long running operation (yeah, concurrency). So expanding on what Fredrick said, if you do spin off a new thread and put up a progress bar, you could lock the focus onto the progress bar to stop a user from interacting with the rest of the application. That should be enough to implement a really simple second thread without really having to worry about concurrency because you're essentially locking out the rest of the app by disabling user interation.
You'll need to interleave the processing with message handling somehow. If threads are out of the question, you might want to look at splitting the processing into multiple phases. One way to do this is to do some processing when you first receive the packet, then post a message to the application saying "continue processing here". When the application receives the "continue processing here" message, it will do some more processing, and either send another "continue processing here" message or finish up.
There are a couple of considerations though:
You need to make sure that the state of the application is consistent every time you post a message to yourself and defer to the message loop, as other message handling might happen in the mean-time. This can be done e.g. by only changing the state in the final processing phase.
Another packet might arrive while you are still processing the first packet. If changing the order of processing would be bad for the application, you could handle this by e.g. posting a "remind me to process this packet later" message when this happens.
I don't know whether this would be feasible within the design of your application, but it would be one way to solve the problem.
If you are unwilling to spawn a worker thread, but you can break the long-running task down into smaller parts, you can do the processing in MFC's CWinApp::OnIdle. This function gets called from within the message pump loop whenever there are no Windows messages waiting. As long as the work you do in each OnIdle call is sufficiently short, you keep your app responsive.
Assuming that it is the processing of the data that is taking up all the time and not the receiving (and you're serious about avoiding a thread - which is fine IMOHO) of the data you could:
In the function that you are currently handling the message, create a modal dialog that shows a "please wait" message (or make it hidden, small, whatever...). Copy (or send a pointer, etc...) the data you're processing to a member variable of that dialog.
In the modal dialog post a user-defined message to yourself to process the data.
In the dialog's message handler, handle one "unit" of work. Keep track what the next "unit" of work is. Post the same message again.
Repeat this post-message "loop" until done. Close your dialog.
The nature of the modal dialog will keep you're application "responsive", with minimal interruption or change to how the application worked previously. Reentrancy can be a problem with modal loops, especially if any of this is involved with a WM_PAINT message. (anyone ever assert inside painting code? good times, good times...)
The dialog could even have a cancel button if you'd like.
I encountered the exact same problem.
Since I dont consider the other answers appealing/straightforward I decided to post this.
Short description and some context:
I am saving data from a grid into a database, and this process can take a while. So I changed the saving method to an asynchronous method and had the same problem.
Then I came up with a simple solution:
//__ENABLE OR DISABLE MAIN DIALOG
void CMFCApplication1Dlg::enableMainDlg(bool enable)
{
this->EnableWindow(enable);
}
When starting the asynchronous method, I disable the main dialog.
This prevents the user from interacting with the main dialog (like starting another saving process which could result in thousands of SQL error messages if I wouldn't check if the saving process is already running...)
When the saving process is finished, I re-enable the main dialog.
Works like a charm, I hope this helps
One way to overcome your application from becoming unresponsive you need to tell the application to process messages from windows. When you are in your loop you can call
Application->ProcessMessages();
I had a similar issue with a win32 app that was waiting on a response from webservice using cpprest (Casablanca) api. My solution was to create a event and thread that does nothing but wait for the cpprest api and then release the thread once it recieves the signal:
DWORD WINAPI WaitForCasablanca(LPVOID n)
{
// Get the handler to the event for which we need to wait in
// this thread.
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "MyEvent");
if (!hEvent) { return -1; }
// Loop through and wait for an event to occur
// Wait for the Event
WaitForSingleObject(hEvent, INFINITE);
// No need to Reset the event as its become non signaled as soon as
// some thread catches the event.
CloseHandle(hEvent);
return 0;}
BOOL WINAPI DlgProc(HWND hDlg, UINT message, WPARAM,wParam, LPARAM lParam) ...
HANDLE hEvent = CreateEvent(NULL, false, false, "MyEvent");//create an event that will wait for casablanca ro authenticate
if (!hEvent) return -1;
// Create a Thread Which will wait for the events to occur
DWORD Id;
HANDLE hThrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaitForCasablanca, 0, 0, &Id);
if (!hThrd) { CloseHandle(hEvent); return -1; }
makeCasablancaRequest(...);
SetEvent(hEvent); //casablanca has finished signal the event to terminate
WaitForSingleObject(hThrd, INFINITE); //wait for thread to die
CloseHandle(hThrd);
CloseHandle(hEvent);
...}
That got rid of the "program not responding" message for me. I believe the problem is the code that is getting the data is running in a thread too- only the main program doesn't know this- so as far as the system is concerned the main program is idling. You need an event and a thread that waits for the event to tell the system the program is waiting on data. I got the code from this tutorial: How to use WIN32 Event Kernel Object