CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 19
  1. #1
    Join Date
    May 2002
    Posts
    1,798

    How to get rid of 'not responding' message

    I have a simple dialog based app that performs some time consuming file manipulations. The activating method contains the customary
    Code:
    CWaitCursor wait;
    The hour glass initially appears, than after a few seconds, the dialog title bar indicates 'not responding'.

    This is misleading to users as it suggests the application has ceased to function when, in fact, it's working just fine. I would like very much
    to eliminate this 'not responding' message but havn't a clue how to do it. Have any of you dealt with this problem, if so, how?

    Thanks.
    mpliam

  2. #2
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: How to get rid of 'not responding' message

    Threads
    Message pump

  3. #3
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: How to get rid of 'not responding' message

    If you are doing the processor intensive file manipulation in the main UI thread, you are blocking the app.

    As mentioned, you either need to do the labor intensive operations in a worker thread, or if doing the operations in the main thread, pump messages while processing.

    Btw, the 'Not responding' message appears when an app hasn't processed any messages within the last 2 seconds. While you might think your app is 'working properly' most users would think your app is hung.

    Generally you shouldn't block the UI because the user can't do anything with the app - they can't cancel the operation, minimize or move the window - not a good user experience.
    Last edited by Arjay; July 30th, 2014 at 06:17 PM.

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: How to get rid of 'not responding' message

    Victor Nijegorodov

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: How to get rid of 'not responding' message

    Quote Originally Posted by Mike Pliam View Post
    I have a simple dialog based app that performs some time consuming file manipulations.
    As it was said many times here, any time consuming manipulation does not belong with main GUI thread.

    The activating method contains the customary
    Code:
    CWaitCursor wait;
    Not sure what activating method really is. In case it's the method where DoModal() is called, I don't think this is going to give you what you expect. The hourglass is to keep showing until dialog closes, in case my guess is correct.

    The hour glass initially appears, than after a few seconds, the dialog title bar indicates 'not responding'.

    This is misleading to users as it suggests the application has ceased to function when, in fact, it's working just fine.
    Working just fine should include dialog responsiveness as well. Besides, hourglass looks more misleading than, say, a progressbar in statusbar or something similar. Hourglass is kinda fossil from Jurassic period.

    I would like very much to eliminate this 'not responding' message but havn't a clue how to do it.
    Quote Originally Posted by GCDEF View Post
    Threads
    Message pump
    Best regards,
    Igor

  6. #6
    Join Date
    May 2002
    Posts
    1,798

    Re: How to get rid of 'not responding' message

    OK. I get it. Thank you all for your suggestions. One of the best examples I've found is that of our beloved Arjay.

    VC++ MFC Thread Tutorial: _beginthreadex, WaitForSingleObject, pausing,
    resuming, and stopping threads. Arjay
    http://www.********.net/Visual_C_MFC...FC-Example.htm

    (For some reason, Codeguru won't let me post the full url - but you can probably google it as that's how I found it.)

    Using this code as a starting point, I tried to insert a test class (CCryptTest) action (EncryptFile(LPCTSTR)) into the ThreadProc of Arjay's CProgressMgr class:

    Code:
    	//+------------------------------------------------------
    	// Secondary thread procedure
    	//+------------------------------------------------------
    	static UINT WINAPI ThreadProc( LPVOID lpContext )
    	{
    		// Turn the passed in 'this' pointer back into a CProgressMgr instance
    		CProgressMgr* pProgressMgr = reinterpret_cast< CProgressMgr* >( lpContext );
    
    		
    		/*
    		
    		for( UINT uCount = 0; uCount < 100; uCount++ )
    		{
    			if( WAIT_OBJECT_0 == WaitForSingleObject( pProgressMgr->GetShutdownEvent( ), 0 ) )
    			{
    				return 1;
    			}
    
    			// Send the progress message to the UI
    			pProgressMgr->NotifyUI( NOTIFY_INC_PROGRESS );
    
    			// Sample code - delay the operation a bit
    			Sleep( 50 );
    
    			//_RPT1(0, "What the **** #%d\n", uCount);
    			//CCryptTest.EncryptFile(L"MyTestFile.txt");
    			CCryptTest::EncryptFile(L"MyTestFile.txt");
    			
    		}
    		*/
    					
    		CCryptTest::EncryptFile(L"MyTestFile.txt");
    
    
    		// Send the thread completed message to the UI
    		pProgressMgr->NotifyUI( NOTIFY_THREAD_COMPLETED );
    
    		return 0;
    	}
    Notice that I have put my action method outside of the thread loop. It works to encrypt the file but, of course, provides no progress notification. Were I to insert it within the loop as I initially attempted to do, it still works quit well, about 100 times, as it provides the expected progress bar notifications.

    So my question at this point is two-fold:
    1 - How do I implement a progress report from the encryption algorithm (one which I have written that resides in a dll) in order to feed back to the progress bar control ?
    2 - How does one estimate what sort of progress percentage of the total task is actually being acomplished (otherwise such progress reporting is rather fictional)?

    If it's a different Arjay, please accept my apologies. If it is our Arjay, thank you for making the very nice code example available.
    Last edited by Mike Pliam; August 1st, 2014 at 11:26 PM.
    mpliam

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: How to get rid of 'not responding' message

    About the percentage. It may be a number of files processed to total number, or number of bytes to total size, whatever. In case the whole work is done inside encrypting method, that one should be responsible for calling some callback or posting progress message.
    Best regards,
    Igor

  8. #8
    Join Date
    May 2002
    Posts
    1,798

    Re: How to get rid of 'not responding' message

    Thanks Igor. Here's a little demo app that calculates the total number of file bytes in each file to be processed, then processes (simply loads a file for demo), calculating the cumulative number of file bytes loaded as a percentage of the total expected. This takes place in the ManipulateFiles method which uses a couple of helper functions to get the bytes from each file. In this demo, the percent 'progress' is printed out.

    What i do not know is how to make or associate this ManipulateFiles with a callback function that would work from within a dll. I've looked at a number of online dll callback demos, the most helpful being:

    Callback Functions Tutorial Posted by Marius Bancila on September 16th, 2005
    http://www.codeguru.com/cpp/cpp/cpp_...s-Tutorial.htm

    but cannot figure out how to do it.

    Any help greatly appreciated. Thanks. : )
    mpliam

  9. #9
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: How to get rid of 'not responding' message

    note that changing the UI elements should only be done FROM the UI thread, never from the worker threads.
    So the proper way to update your UI is to post a message to the UI thread or window to inform it of a percentage change.

  10. #10
    Join Date
    May 2002
    Posts
    1,798

    Re: How to get rid of 'not responding' message

    the proper way to update your UI is to post a message to the UI thread or window to inform it of a percentage change
    Yes. That would be nice. But cannot figure out how to get that to work.

    Say I have a dll method like that in the ProgFeedBack program posted in this thread, and I code as follows:
    Code:
    // global definition in dll class
    UINT __declspec(selectany) WM_PROGRESS = 9;  
    #define WM_PROGSTR _T("Progress")
    
    WM_PROGRESS = RegisterWindowMessage(WM_PROGSTR); // (in ctor of that class)
    
    void CMyDllClass::ManipulateFiles(...)
    {
    	for(size_t i = 0; i < vFilesIn.size(); i++)
    	{
    		CurrentFileBytes = LoadFile((char*)sfile.c_str()); 
    		CumulativeBytesLoaded += (float)CurrentFileBytes;
    		PercentTotalBytes = (float) CumulativeBytesLoaded / (float)TotalFileBytes;
    		::PostMessageW(NULL, WM_PROGRESS, (WPARAM) PercentTotalBytes, 0);
    	}
    }
    Now this might work - but I do not know how to create a GetMessage loop in the User Interface thread that will capture the series of posted messages. Or is this completely erroneous in approach and should I try to fashion some callback function?
    mpliam

  11. #11
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: How to get rid of 'not responding' message

    Quote Originally Posted by Mike Pliam View Post
    Now this might work - but I do not know how to create a GetMessage loop in the User Interface thread that will capture the series of posted messages. Or is this completely erroneous in approach and should I try to fashion some callback function?
    In MFC you usually don't call GetMessage directly. The Framework does it for you.
    But you must implement a message handler (in the GUI thread window) for the user defined message being posted by threads.
    See the essay I referred to in the post#4
    Victor Nijegorodov

  12. #12
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: How to get rid of 'not responding' message

    Quote Originally Posted by Mike Pliam View Post
    What i do not know is how to make or associate this ManipulateFiles with a callback function that would work from within a dll.
    GUI <- Callback <- DLL sample attached
    ProgFeedBack_callback.zip
    Best regards,
    Igor

  13. #13
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: How to get rid of 'not responding' message

    If the dll manages the thread, then what Igor said:

    GUI <- Callback <- DLL sample attached

    If not,

    GUI <- Thread <- Callback <- DLL

    P.S. Thank you for the kudos for my threading sample. I've been very busy lately; otherwise I would have responded sooner.

  14. #14
    Join Date
    May 2002
    Posts
    1,798

    Re: How to get rid of 'not responding' message

    I'm still trying to digest Igor's code. While it's easy to copy and paste, understanding it is quite another matter for me. I've got it working in my own mileau, having separated the dll project and the GUI project more succinctly, but in either case I notice that if one selects Cancel before the progress has fully updated, a large memory leak occurs. Any good way to prevent this leak from happening?

    Additionally, Arjay's remarks leave me a bit puzzled. They suggest that Igor's callback method does not involve a worker thread when, in fact, the 'not responding' message is gone and one can move and/or Cancel the progress operation, suggesting that it must be operating in a separate thread. I'm afraid I'm confused as usual.
    Last edited by Mike Pliam; August 5th, 2014 at 12:22 PM.
    mpliam

  15. #15
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: How to get rid of 'not responding' message

    Mike, the sample was made to be a simplistic representation of C-style callback use in GUI. Your additional DLL aspect adds almost nothing to it, but as long as you asked for it, the demo includes one as well.

    Now let's see what we have. A GUI app which main thread is not to be blocked. The instrument for unblocking is Worker thread. The thread being created calls DLL code, Run function in particular.

    What GUI app knows about DLL? It's only Run function accepting a function pointer of certain prototype, i.e. the callback.

    What DLL knows about host app? Nothing but a callback function to be called.

    What callback function knows about DLL? Effectively, almost nothing, as it's only a set of parameters the DLL passes to it. But it knows all the details about app code, the details enough to update the GUI controls, i.e. progress bar in our case, in accordance with the passed information.

    So, interoperation is provided by establishing a well-defined data exchange interface in a form of DLL export function and callback prototype the former accepts. DLL just does its work and calls the callback with the values it produces on the run. App just initiates the DLL call and waits for its return. Nevertheless, while it waits the callback function is called by DLL. It appears to be driven by the DLL function.

    It's worth to mention, that GUI app can be replaced with a console app alright, and this won't change things for DLL at all. Say, the callback making use of printf will do perfect for it.
    Last edited by Igor Vartanov; August 5th, 2014 at 02:29 PM.
    Best regards,
    Igor

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured