Thread
-
Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //
-
Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //
-
Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //
You can't use MFC windows in multiple threads. Since
CFrameWnd::GetActiveDocument()
is MFC specific (not a Win32 function) you're pretty much screwed. You'll need to either pass the document as a parameter to your thread function, or find another way of doing it. MFC is just no good for applications where multiple threads manipulate the GUI. Ryan Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact" -
Could you explain little bit more what is the following code does? metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); P.S. I assume "<" and ">" are lost due to the editor.
Hi AlexO, metprof *metProfPtr = static_cast<>(pvParam); CTestSDIDoc *pDoc = static_cast<>(pvParam); These are pointers to metProf dialog class to access dialog controls like editBox etc... The second one is a pointer too but to the Document. If I run my program, I got an assertion but if I click on ignore button the program continues to work correctly. Thanks for your help, Rene
-
Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //
Pass all the data the thread will need as the parameter:
struct ThreadData
{
CTestSDIDoc *pDoc;
metprof *metProfPtr;
.
. //Your data here.
.
HWND hWnd; //Pass CWnd objects by HWND.
};.
.
.
ThreadData *td = new ThreadData//Do this before starting thread.
td.pDoc = CTestSDIDoc::GetDoc();
td.metProfPtr = ... //Set this too.//Thread function must delete td!
CWinThread *pThread = AfxBeginThread(ThreadProc, (LPVOID)td);
.
.
.UINT ThreadProc(LPVOID lpParam)
{
ThreadData *td = (ThreadData *)lpParam;
.
. //Your code here.
.
delete td; //Delete memory so no leaks.
return 0;
}Also, you don't need a thread just to create a proccess. Hope this helps... :) Jonathan Craig www.mcw-tech.com
-
Hi AlexO, metprof *metProfPtr = static_cast<>(pvParam); CTestSDIDoc *pDoc = static_cast<>(pvParam); These are pointers to metProf dialog class to access dialog controls like editBox etc... The second one is a pointer too but to the Document. If I run my program, I got an assertion but if I click on ignore button the program continues to work correctly. Thanks for your help, Rene
-
Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //
Have a look at Jonathan Craig's post above this one. If that doesn't help drop me an email [click on the email button at the bottom of this post] and I'll help you out. Regards, Brian Dela :-)
-
Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //
When the secondary thread finishes up a work unit, it simply needs to post a message to the primary thread (i.e., the one that owns the UI).
-
Pass all the data the thread will need as the parameter:
struct ThreadData
{
CTestSDIDoc *pDoc;
metprof *metProfPtr;
.
. //Your data here.
.
HWND hWnd; //Pass CWnd objects by HWND.
};.
.
.
ThreadData *td = new ThreadData//Do this before starting thread.
td.pDoc = CTestSDIDoc::GetDoc();
td.metProfPtr = ... //Set this too.//Thread function must delete td!
CWinThread *pThread = AfxBeginThread(ThreadProc, (LPVOID)td);
.
.
.UINT ThreadProc(LPVOID lpParam)
{
ThreadData *td = (ThreadData *)lpParam;
.
. //Your code here.
.
delete td; //Delete memory so no leaks.
return 0;
}Also, you don't need a thread just to create a proccess. Hope this helps... :) Jonathan Craig www.mcw-tech.com
Gandilf emailed me: Your struct trick works perfectly but now I got an exception 0xC0000005 about metProfPtr. metProfPtr is a pointer to the current dialog (my own progress bar and bitmap, etc...). I need it to unhide one different bitmap at each process completion (total of processes: 6). When you talk about initializing pointer metprofPtr like td.pDoc = CTestSDIDoc::GetDoc(); for pDoc, what can I do ? (td.metProfPtr = 0 ?) Maybe you have another suggestion. Thanks a lot, Rene There are two different ways to do it. 1.) Add the pointer to the dialog to the ThreadData struct.
struct ThreadData
{
.
CMyDialog *pDlg;
.
};td.pDlg = this;
This may or may not cause problems when calling methods on td->pDlg. 2.) If you know which object you wish to hide or show, you can pass a HWND handle to it. If your bitmap object is a CStatic.
struct ThreadData
{
.
HWND hWnd;
.
};td.hWnd = m_bitmap.GetSafeHwnd();
In your thread you would call.
::ShowWindow(td->hWnd, SW_HIDE);
or
::ShowWindow(td->hWnd, SW_SHOW);
This is the correct way to pass window objects to a thread. Good Luck :) Jonathan Craig www.mcw-tech.com