Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. WaitForSingleObject best practices

WaitForSingleObject best practices

Scheduled Pinned Locked Moved C / C++ / MFC
12 Posts 4 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    ForNow
    wrote on last edited by
    #1

    Hi I am looking to be Notified When something is downloaded to my FTP folder towards that end I have implemented FindFirstChangeNotification being a mainframe programmer its taken a while to get used that when I do a Wait I stop the entire thread So I have 2 options put the wait in a different thread or.... code a timer value other then infinite and in the case of WAIT_TIMEOUT loop "while(TRUE)" and Only "break when the object is signaled

    D L 2 Replies Last reply
    0
    • F ForNow

      Hi I am looking to be Notified When something is downloaded to my FTP folder towards that end I have implemented FindFirstChangeNotification being a mainframe programmer its taken a while to get used that when I do a Wait I stop the entire thread So I have 2 options put the wait in a different thread or.... code a timer value other then infinite and in the case of WAIT_TIMEOUT loop "while(TRUE)" and Only "break when the object is signaled

      D Offline
      D Offline
      David Crow
      wrote on last edited by
      #2

      ForNow wrote:

      ...when I do a Wait I stop the entire thread...

      The wait functions WaitForSingleObject() and WaitForMultipleObjects() do not block.

      "One man's wage rise is another man's price increase." - Harold Wilson

      "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

      "You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles

      1 Reply Last reply
      0
      • F ForNow

        Hi I am looking to be Notified When something is downloaded to my FTP folder towards that end I have implemented FindFirstChangeNotification being a mainframe programmer its taken a while to get used that when I do a Wait I stop the entire thread So I have 2 options put the wait in a different thread or.... code a timer value other then infinite and in the case of WAIT_TIMEOUT loop "while(TRUE)" and Only "break when the object is signaled

        L Offline
        L Offline
        leon de boer
        wrote on last edited by
        #3

        Usually you don't stop an entire thread while waiting you are forced to do it with MFC, so I am guessing this is your MFC program again. Within MFC personally I would create a thread which just spins it wheels checking whatever and the thread simply posts a message back when an interesting event occurs. I wouldn't be putting the wait I would be putting the whole code that requires the wait in a thread and use messages to communicate with the MFC code. So make a proper worker thread.

        In vino veritas

        F 1 Reply Last reply
        0
        • L leon de boer

          Usually you don't stop an entire thread while waiting you are forced to do it with MFC, so I am guessing this is your MFC program again. Within MFC personally I would create a thread which just spins it wheels checking whatever and the thread simply posts a message back when an interesting event occurs. I wouldn't be putting the wait I would be putting the whole code that requires the wait in a thread and use messages to communicate with the MFC code. So make a proper worker thread.

          In vino veritas

          F Offline
          F Offline
          ForNow
          wrote on last edited by
          #4

          So you are saying creating a new thread to wait for notification is a better choice then an ifinate loop with say A 1000 millisecond in the WaitForSingleObject only breaking out of the loop when the event is signaled Truth is a new thread leaves the CPU time distribution up to Windows Thanks

          L 1 Reply Last reply
          0
          • F ForNow

            So you are saying creating a new thread to wait for notification is a better choice then an ifinate loop with say A 1000 millisecond in the WaitForSingleObject only breaking out of the loop when the event is signaled Truth is a new thread leaves the CPU time distribution up to Windows Thanks

            L Offline
            L Offline
            leon de boer
            wrote on last edited by
            #5

            It's a low priority Hotwatch .. it will always be better to do as a thread and it isn't hard

            // Define a structure to pass to thread
            typedef struct _MYWATCHERDATA {
            HWND AppWindow; // Application window to post message to
            UINT MsgId; // Your private message ID will be WM_APP + some number
            WPARAM CmdId; // Command ID .. perhaps you have multiple of these watchers
            char* FolderToWatch; // The string nominating the folder to watch
            HANDLE dwChangeHandles[2]; // These will be thread wait handles (1 for it, 1 for me to force exit)
            BOOL threadExitComplete; // Thread exit completed
            } WATCHERDATA;

            // This is the thread routine
            // Pass an initialized structure in on LPARAM Of CreateThread
            DWORD WINAPI NotifyMeOfFolderChangeThread(LPVOID lpParam) // thread procedure
            {
            BOOL exitSignal = FALSE; // Preset exit signal to false
            WATCHERDATA* watchData = (WATCHERDATA*)lpParam; // Typecast the lParam to your structure you pass in

            // Watch Handle\[0\] belongs to this thread 
            watchData->dwChangeHandles\[0\] =
            	FindFirstChangeNotification(watchData->FolderToWatch, // folder path passed in
            		FALSE,										      // no subfolders
            		FILE\_NOTIFY\_CHANGE\_FILE\_NAME);				      // watch for renaming, creating, or deleting a file
            
            if (INVALID\_HANDLE\_VALUE == watchData->dwChangeHandles\[0\])// Error something is dorked probably folder doesn't exist
            {
            	DWORD dwError = ::GetLastError();
            	// handle error
            	return dwError;
            }
            
            while (exitSignal == FALSE) {
            	// Okay we wait on the notification signal or exernal exit signal
            	DWORD dwWaitStatus = WaitForMultipleObjects(2, 
            		watchData->dwChangeHandles, FALSE, INFINITE);
            	
            	switch (dwWaitStatus) {
            		// Wait exit was from directory change
            		case WAIT\_OBJECT\_0:
            			// Post off message back to application window.
            			PostMessage(watchData->AppWindow, watchData->MsgId,
            				watchData->CmdId, (LPARAM)watchData->FolderToWatch);
            			FindNextChangeNotification(watchData->dwChangeHandles\[0\]);
            			break;
            		// External thread signal forcing thread to break out and exit
            		case WAIT\_OBJECT\_0 + 1:
            			exitSignal = TRUE;           // Yep time to exit
            			break;
            	}
            }
            watchData->threadExitComplete = TRUE; // Thread has finished with watchData .. tell app that
            return 0;
            

            }

            The use of the thread involves, initialize, use, wait for thread to exit .. cleanup

            // Initialize a WATCHERDATA structure
            char* watchDirectory = "c:\\temp\\";

            F J 3 Replies Last reply
            0
            • L leon de boer

              It's a low priority Hotwatch .. it will always be better to do as a thread and it isn't hard

              // Define a structure to pass to thread
              typedef struct _MYWATCHERDATA {
              HWND AppWindow; // Application window to post message to
              UINT MsgId; // Your private message ID will be WM_APP + some number
              WPARAM CmdId; // Command ID .. perhaps you have multiple of these watchers
              char* FolderToWatch; // The string nominating the folder to watch
              HANDLE dwChangeHandles[2]; // These will be thread wait handles (1 for it, 1 for me to force exit)
              BOOL threadExitComplete; // Thread exit completed
              } WATCHERDATA;

              // This is the thread routine
              // Pass an initialized structure in on LPARAM Of CreateThread
              DWORD WINAPI NotifyMeOfFolderChangeThread(LPVOID lpParam) // thread procedure
              {
              BOOL exitSignal = FALSE; // Preset exit signal to false
              WATCHERDATA* watchData = (WATCHERDATA*)lpParam; // Typecast the lParam to your structure you pass in

              // Watch Handle\[0\] belongs to this thread 
              watchData->dwChangeHandles\[0\] =
              	FindFirstChangeNotification(watchData->FolderToWatch, // folder path passed in
              		FALSE,										      // no subfolders
              		FILE\_NOTIFY\_CHANGE\_FILE\_NAME);				      // watch for renaming, creating, or deleting a file
              
              if (INVALID\_HANDLE\_VALUE == watchData->dwChangeHandles\[0\])// Error something is dorked probably folder doesn't exist
              {
              	DWORD dwError = ::GetLastError();
              	// handle error
              	return dwError;
              }
              
              while (exitSignal == FALSE) {
              	// Okay we wait on the notification signal or exernal exit signal
              	DWORD dwWaitStatus = WaitForMultipleObjects(2, 
              		watchData->dwChangeHandles, FALSE, INFINITE);
              	
              	switch (dwWaitStatus) {
              		// Wait exit was from directory change
              		case WAIT\_OBJECT\_0:
              			// Post off message back to application window.
              			PostMessage(watchData->AppWindow, watchData->MsgId,
              				watchData->CmdId, (LPARAM)watchData->FolderToWatch);
              			FindNextChangeNotification(watchData->dwChangeHandles\[0\]);
              			break;
              		// External thread signal forcing thread to break out and exit
              		case WAIT\_OBJECT\_0 + 1:
              			exitSignal = TRUE;           // Yep time to exit
              			break;
              	}
              }
              watchData->threadExitComplete = TRUE; // Thread has finished with watchData .. tell app that
              return 0;
              

              }

              The use of the thread involves, initialize, use, wait for thread to exit .. cleanup

              // Initialize a WATCHERDATA structure
              char* watchDirectory = "c:\\temp\\";

              F Offline
              F Offline
              ForNow
              wrote on last edited by
              #6

              thanks so much

              1 Reply Last reply
              0
              • L leon de boer

                It's a low priority Hotwatch .. it will always be better to do as a thread and it isn't hard

                // Define a structure to pass to thread
                typedef struct _MYWATCHERDATA {
                HWND AppWindow; // Application window to post message to
                UINT MsgId; // Your private message ID will be WM_APP + some number
                WPARAM CmdId; // Command ID .. perhaps you have multiple of these watchers
                char* FolderToWatch; // The string nominating the folder to watch
                HANDLE dwChangeHandles[2]; // These will be thread wait handles (1 for it, 1 for me to force exit)
                BOOL threadExitComplete; // Thread exit completed
                } WATCHERDATA;

                // This is the thread routine
                // Pass an initialized structure in on LPARAM Of CreateThread
                DWORD WINAPI NotifyMeOfFolderChangeThread(LPVOID lpParam) // thread procedure
                {
                BOOL exitSignal = FALSE; // Preset exit signal to false
                WATCHERDATA* watchData = (WATCHERDATA*)lpParam; // Typecast the lParam to your structure you pass in

                // Watch Handle\[0\] belongs to this thread 
                watchData->dwChangeHandles\[0\] =
                	FindFirstChangeNotification(watchData->FolderToWatch, // folder path passed in
                		FALSE,										      // no subfolders
                		FILE\_NOTIFY\_CHANGE\_FILE\_NAME);				      // watch for renaming, creating, or deleting a file
                
                if (INVALID\_HANDLE\_VALUE == watchData->dwChangeHandles\[0\])// Error something is dorked probably folder doesn't exist
                {
                	DWORD dwError = ::GetLastError();
                	// handle error
                	return dwError;
                }
                
                while (exitSignal == FALSE) {
                	// Okay we wait on the notification signal or exernal exit signal
                	DWORD dwWaitStatus = WaitForMultipleObjects(2, 
                		watchData->dwChangeHandles, FALSE, INFINITE);
                	
                	switch (dwWaitStatus) {
                		// Wait exit was from directory change
                		case WAIT\_OBJECT\_0:
                			// Post off message back to application window.
                			PostMessage(watchData->AppWindow, watchData->MsgId,
                				watchData->CmdId, (LPARAM)watchData->FolderToWatch);
                			FindNextChangeNotification(watchData->dwChangeHandles\[0\]);
                			break;
                		// External thread signal forcing thread to break out and exit
                		case WAIT\_OBJECT\_0 + 1:
                			exitSignal = TRUE;           // Yep time to exit
                			break;
                	}
                }
                watchData->threadExitComplete = TRUE; // Thread has finished with watchData .. tell app that
                return 0;
                

                }

                The use of the thread involves, initialize, use, wait for thread to exit .. cleanup

                // Initialize a WATCHERDATA structure
                char* watchDirectory = "c:\\temp\\";

                F Offline
                F Offline
                ForNow
                wrote on last edited by
                #7

                Leon Just wanted to tell you again you are correct I have Sockets in my code So Typically after I do CAsynSocket connect I do the send after I get the OnSend Notification From The FrameWork My Sockets has a CWinThread Wrapper, However the notification like OnSend comes in The Context of the Main Thread Since I put WaitFor...Object api (In The Main Thread) even though I didn't have INFINITE it messed up the Windows Dispatcher and I wasn't getting the notification I am going to try your code out Shortly Thanks again

                L 2 Replies Last reply
                0
                • F ForNow

                  Leon Just wanted to tell you again you are correct I have Sockets in my code So Typically after I do CAsynSocket connect I do the send after I get the OnSend Notification From The FrameWork My Sockets has a CWinThread Wrapper, However the notification like OnSend comes in The Context of the Main Thread Since I put WaitFor...Object api (In The Main Thread) even though I didn't have INFINITE it messed up the Windows Dispatcher and I wasn't getting the notification I am going to try your code out Shortly Thanks again

                  L Offline
                  L Offline
                  leon de boer
                  wrote on last edited by
                  #8

                  Yes that is a generic schema for not doing that sort of thing ... I hacked the MSDN thread sample. When I do socket apps I do exactly the same schema I have a write thread and a read thread of exactly the form above. The socket IO structures and objects are held in the memory block. Basically you want your app just dealing with messages not sitting around doing things .. bring up task manager and look at the number of threads running normally. It really expects and wants this sort of behaviour, it's designed around it. Lifetime of app threads in particular are extremely easy because you can launch them on the WM_CREATE of the main app window and dispose of them in the WM_DESTROY. You don't have the problem of who is responsible for the shared data and memory (and it's cleanup) that you have with intermittent start and stop threads. The app window handle to pass to the thread to message you also can't get wrong :-) They give you huge blocks of message ids at WM_APP and WM_USER to allow you to do it. All those ID's you are free to use but you might want to check MFC might use a few (that is why I jumped 100) and they may restrict the range down a little.

                  In vino veritas

                  1 Reply Last reply
                  0
                  • F ForNow

                    Leon Just wanted to tell you again you are correct I have Sockets in my code So Typically after I do CAsynSocket connect I do the send after I get the OnSend Notification From The FrameWork My Sockets has a CWinThread Wrapper, However the notification like OnSend comes in The Context of the Main Thread Since I put WaitFor...Object api (In The Main Thread) even though I didn't have INFINITE it messed up the Windows Dispatcher and I wasn't getting the notification I am going to try your code out Shortly Thanks again

                    L Offline
                    L Offline
                    leon de boer
                    wrote on last edited by
                    #9

                    Present for you as I checked my code putting it into an application Code: Folder watcher code[^] Compiled EXE:Folder HotWatcher EXE[^] It's a full folder watcher app with a basic watcher thread and detailed watcher thread. Basic just tells you if the folder changed, Detailed tells you file changes and what action was done. Basically run the app select an unimportant directory like c:\temp and then copy, delete, rename files to the directory and you will see the messages reported to the app.

                    In vino veritas

                    F 1 Reply Last reply
                    0
                    • L leon de boer

                      Present for you as I checked my code putting it into an application Code: Folder watcher code[^] Compiled EXE:Folder HotWatcher EXE[^] It's a full folder watcher app with a basic watcher thread and detailed watcher thread. Basic just tells you if the folder changed, Detailed tells you file changes and what action was done. Basically run the app select an unimportant directory like c:\temp and then copy, delete, rename files to the directory and you will see the messages reported to the app.

                      In vino veritas

                      F Offline
                      F Offline
                      ForNow
                      wrote on last edited by
                      #10

                      leon thanks so much I implemented the code and problems went away meaning with out the wait in the Main Thread The Framework was able to notify me via CAsynSocket::OnSend The actual testing will come when I execute my Z/OS (MainFrame) FTP code to download the file to that folder that is being watched Much thanks

                      J 1 Reply Last reply
                      0
                      • L leon de boer

                        It's a low priority Hotwatch .. it will always be better to do as a thread and it isn't hard

                        // Define a structure to pass to thread
                        typedef struct _MYWATCHERDATA {
                        HWND AppWindow; // Application window to post message to
                        UINT MsgId; // Your private message ID will be WM_APP + some number
                        WPARAM CmdId; // Command ID .. perhaps you have multiple of these watchers
                        char* FolderToWatch; // The string nominating the folder to watch
                        HANDLE dwChangeHandles[2]; // These will be thread wait handles (1 for it, 1 for me to force exit)
                        BOOL threadExitComplete; // Thread exit completed
                        } WATCHERDATA;

                        // This is the thread routine
                        // Pass an initialized structure in on LPARAM Of CreateThread
                        DWORD WINAPI NotifyMeOfFolderChangeThread(LPVOID lpParam) // thread procedure
                        {
                        BOOL exitSignal = FALSE; // Preset exit signal to false
                        WATCHERDATA* watchData = (WATCHERDATA*)lpParam; // Typecast the lParam to your structure you pass in

                        // Watch Handle\[0\] belongs to this thread 
                        watchData->dwChangeHandles\[0\] =
                        	FindFirstChangeNotification(watchData->FolderToWatch, // folder path passed in
                        		FALSE,										      // no subfolders
                        		FILE\_NOTIFY\_CHANGE\_FILE\_NAME);				      // watch for renaming, creating, or deleting a file
                        
                        if (INVALID\_HANDLE\_VALUE == watchData->dwChangeHandles\[0\])// Error something is dorked probably folder doesn't exist
                        {
                        	DWORD dwError = ::GetLastError();
                        	// handle error
                        	return dwError;
                        }
                        
                        while (exitSignal == FALSE) {
                        	// Okay we wait on the notification signal or exernal exit signal
                        	DWORD dwWaitStatus = WaitForMultipleObjects(2, 
                        		watchData->dwChangeHandles, FALSE, INFINITE);
                        	
                        	switch (dwWaitStatus) {
                        		// Wait exit was from directory change
                        		case WAIT\_OBJECT\_0:
                        			// Post off message back to application window.
                        			PostMessage(watchData->AppWindow, watchData->MsgId,
                        				watchData->CmdId, (LPARAM)watchData->FolderToWatch);
                        			FindNextChangeNotification(watchData->dwChangeHandles\[0\]);
                        			break;
                        		// External thread signal forcing thread to break out and exit
                        		case WAIT\_OBJECT\_0 + 1:
                        			exitSignal = TRUE;           // Yep time to exit
                        			break;
                        	}
                        }
                        watchData->threadExitComplete = TRUE; // Thread has finished with watchData .. tell app that
                        return 0;
                        

                        }

                        The use of the thread involves, initialize, use, wait for thread to exit .. cleanup

                        // Initialize a WATCHERDATA structure
                        char* watchDirectory = "c:\\temp\\";

                        J Offline
                        J Offline
                        Joe Woodbury
                        wrote on last edited by
                        #11

                        while (myWatch->threadExitComplete == FALSE) {};

                        In this example,

                        WaitForSingleObject(workerThread, INFINITE)

                        would be better. For the handle array in the thread, prefer putting the stop event first to ensure it has a higher priority. I'd also directly test:

                        if (dwWaitStatus == WAIT_OBJECT_0)
                        break;

                        Since you aren't looking at any other conditions, you don't need to check for them.

                        1 Reply Last reply
                        0
                        • F ForNow

                          leon thanks so much I implemented the code and problems went away meaning with out the wait in the Main Thread The Framework was able to notify me via CAsynSocket::OnSend The actual testing will come when I execute my Z/OS (MainFrame) FTP code to download the file to that folder that is being watched Much thanks

                          J Offline
                          J Offline
                          Joe Woodbury
                          wrote on last edited by
                          #12

                          Be aware that the change folder notification occurs at any change, which means the full write may not have happened. One solution is to write the file to another location and then atomically move it to the monitored directory.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups