Change value to a thread
-
I indent to use FindFirstChangeNotification in a class static method in order to use it in a thread, something like this:
DWORD WINAPI FilesWatchDogThread(LPVOID lpParam)
{
HANDLE hFileChange = ::FindFirstChangeNotification((LPCTSTR)lpParam, // folder path
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME);
if(INVALID_HANDLE_VALUE == hFileChange)
{
DWORD dwError = ::GetLastError();
return dwError;
}while(TRUE)
{
::WaitForSingleObject(hFileChange, INFINITE);
// do my job
::FindNextChangeNotification(hFileChange);
}
return 0;
}// somewhere …
::CreateThread(NULL, 0, &CMyClass::FilesWatchDogThread, _T("c:\\temp"), 0, NULL);but how can Itell the thread when a folder to watch has been changed (I mean _T("c:\\temp") change to _T("e:\\whatever")) ? What should I use for that ? CreateEvent or what ?
Yes, you can use CreateEvent, change the folder, set its value in lpParam, then SetEvent to let the thread to reread lpParam and continue to work with a new folder. Note, that thread must now wait for multiple objects!
-
Yes, you can use CreateEvent, change the folder, set its value in lpParam, then SetEvent to let the thread to reread lpParam and continue to work with a new folder. Note, that thread must now wait for multiple objects!
-
Have a look at the [WorkerThreads](http://www.flounder.com/workerthreads.htm) essay of Joe Newcomer. It is MFC issue, but the main concept is the same as for plain Win32 API. Just look at the sections: Pausing a Thread and Thread Shutdown Shutting down a thread from a view or main frame Thread Shutdown Without Polling (Well, you would need something similar to "Pausing" event.
-
Have a look at the [WorkerThreads](http://www.flounder.com/workerthreads.htm) essay of Joe Newcomer. It is MFC issue, but the main concept is the same as for plain Win32 API. Just look at the sections: Pausing a Thread and Thread Shutdown Shutting down a thread from a view or main frame Thread Shutdown Without Polling (Well, you would need something similar to "Pausing" event.
-
Have a look at the [WorkerThreads](http://www.flounder.com/workerthreads.htm) essay of Joe Newcomer. It is MFC issue, but the main concept is the same as for plain Win32 API. Just look at the sections: Pausing a Thread and Thread Shutdown Shutting down a thread from a view or main frame Thread Shutdown Without Polling (Well, you would need something similar to "Pausing" event.
-
I have two questions: 1. Why should I use CreateEvent, and if I should, where ? 2. Why should I use WaitForMultipleObjects instead of WaitForSingleObject ?
1. to inform the worker thread that it must do something (to change the folder in your case). CreateEvent/SetEvent - in the main thread. 2. Because there is already one object: hFileChange. However the thread should react also to the second object created/set by CreateEvent/SetEvent in the main thread.
-
Ask and you shall receive .. that is it straight on the windows API. GitHub - LdB-ECM/FolderWatcher[^] There is both the detailed and basic thread monitor code. There is a compiled exe in release/debug if you just want to run and see it.
In vino veritas
-
Yes, you can use CreateEvent, change the folder, set its value in lpParam, then SetEvent to let the thread to reread lpParam and continue to work with a new folder. Note, that thread must now wait for multiple objects!
Here is what I've done:
// TestFileView.h : interface of the CTestFileView class
protected:
CEvent m_event;
CString m_sFolder;
CWinThread* m_pWinThread;/*static*/UINT CTestFileView::FilesWatchDogThread(LPVOID lpParam)
{
CTestFileView* pView = (CTestFileView*)lpParam;if (NULL == pView->GetSafeHwnd()) return 1; HANDLE hChange = FindFirstChangeNotification(pView->GetFolder(), FALSE, FILE\_NOTIFY\_CHANGE\_FILE\_NAME); if (INVALID\_HANDLE\_VALUE == hChange) return 1; HANDLE aHandles\[2\]; aHandles\[0\] = hChange; aHandles\[1\] = pView->m\_event.m\_hObject; BOOL bContinue = TRUE; while (bContinue) { DWORD dwResult = WaitForMultipleObjects(2, aHandles, FALSE, INFINITE); switch (dwResult) { case WAIT\_OBJECT\_0: ::PostMessage(pView->GetSafeHwnd(), WMU\_NOTIFY\_FOLDERCHANGED, 0, (LPARAM)0); FindNextChangeNotification(hChange); break; case WAIT\_OBJECT\_0 + 1: bContinue = FALSE; break; } } FindCloseChangeNotification(hChange); return 0;
}
and
void CTestFileView::StopThread()
{
m_event.SetEvent();
WaitForSingleObject(&m_event, INFINITE);
}and
void CTestFileView::OnEditStartthread()
{
// TODO: Add your command handler code herem\_event.ResetEvent(); m\_sFolder.Format(\_T("D:\\\\Tempx\\\\")); m\_pWinThread = AfxBeginThread(&CTestFileView::FilesWatchDogThread, (LPVOID)this, THREAD\_PRIORITY\_NORMAL, CREATE\_SUSPENDED, 0, NULL);
}
there is remain one thing to do: to change the folder (m_sFolder) how can I complete this with CreateEvent/SetEvent ?
-
Here is what I've done:
// TestFileView.h : interface of the CTestFileView class
protected:
CEvent m_event;
CString m_sFolder;
CWinThread* m_pWinThread;/*static*/UINT CTestFileView::FilesWatchDogThread(LPVOID lpParam)
{
CTestFileView* pView = (CTestFileView*)lpParam;if (NULL == pView->GetSafeHwnd()) return 1; HANDLE hChange = FindFirstChangeNotification(pView->GetFolder(), FALSE, FILE\_NOTIFY\_CHANGE\_FILE\_NAME); if (INVALID\_HANDLE\_VALUE == hChange) return 1; HANDLE aHandles\[2\]; aHandles\[0\] = hChange; aHandles\[1\] = pView->m\_event.m\_hObject; BOOL bContinue = TRUE; while (bContinue) { DWORD dwResult = WaitForMultipleObjects(2, aHandles, FALSE, INFINITE); switch (dwResult) { case WAIT\_OBJECT\_0: ::PostMessage(pView->GetSafeHwnd(), WMU\_NOTIFY\_FOLDERCHANGED, 0, (LPARAM)0); FindNextChangeNotification(hChange); break; case WAIT\_OBJECT\_0 + 1: bContinue = FALSE; break; } } FindCloseChangeNotification(hChange); return 0;
}
and
void CTestFileView::StopThread()
{
m_event.SetEvent();
WaitForSingleObject(&m_event, INFINITE);
}and
void CTestFileView::OnEditStartthread()
{
// TODO: Add your command handler code herem\_event.ResetEvent(); m\_sFolder.Format(\_T("D:\\\\Tempx\\\\")); m\_pWinThread = AfxBeginThread(&CTestFileView::FilesWatchDogThread, (LPVOID)this, THREAD\_PRIORITY\_NORMAL, CREATE\_SUSPENDED, 0, NULL);
}
there is remain one thing to do: to change the folder (m_sFolder) how can I complete this with CreateEvent/SetEvent ?
"Go to ParentYes, you can use CreateEvent, change the folder, set its value in lpParam, then SetEvent to let the thread to reread lpParam and continue to work with a new folder" To create a third event which stop the thread and restart FilesWatchDogThread method with new folder value ?
-
"Go to ParentYes, you can use CreateEvent, change the folder, set its value in lpParam, then SetEvent to let the thread to reread lpParam and continue to work with a new folder" To create a third event which stop the thread and restart FilesWatchDogThread method with new folder value ?
yes, you create the third event and NOT to stop thread, but to change the folder! Something like:
case WAIT\_OBJECT\_0 + 2: FindCloseChangeNotification(hChange); hChange = FindFirstChangeNotification(pView->GetFolder(), FALSE, FILE\_NOTIFY\_CHANGE\_FILE\_NAME); aHandles\[1\] = pView->m\_event.m\_hObject;
And don't forget to set the new folder from the main thread BEFORE setting this event!
-
yes, you create the third event and NOT to stop thread, but to change the folder! Something like:
case WAIT\_OBJECT\_0 + 2: FindCloseChangeNotification(hChange); hChange = FindFirstChangeNotification(pView->GetFolder(), FALSE, FILE\_NOTIFY\_CHANGE\_FILE\_NAME); aHandles\[1\] = pView->m\_event.m\_hObject;
And don't forget to set the new folder from the main thread BEFORE setting this event!
-
yes, you create the third event and NOT to stop thread, but to change the folder! Something like:
case WAIT\_OBJECT\_0 + 2: FindCloseChangeNotification(hChange); hChange = FindFirstChangeNotification(pView->GetFolder(), FALSE, FILE\_NOTIFY\_CHANGE\_FILE\_NAME); aHandles\[1\] = pView->m\_event.m\_hObject;
And don't forget to set the new folder from the main thread BEFORE setting this event!
-
Yes! Sorry for the typo! :sigh: