Accessing CView controls from worker thread
Is it possible for a worker thread to access and update control on a CView of the main application thread? I have a worker thread the sleeps for a set number of seconds via the WaitForSingleObject() funtion. When it timesout, I do some processing and go back to sleep. This continues until the Kill event is returned in the wait. During my processing, I want to update a listbox and start and avi playing on the cview and the stop the avi just before the thread goes to sleep again. Since the controls are not part of the thread, I am not sure how to access them. I tried the following:
UINT CPickThread::threadProc ()
{
DWORD dwResult;
CAWIMSApp* pApp = (CAWIMSApp*)AfxGetApp();
CString t_cConnect;
CDatabase t_PickDB;
CPickQueueSet rsPickQueue;
// Here is the work to be done !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int t_iRefresh;
t_iRefresh=pApp->GetProfileInt("AWIMS Client","PQ_Refresh_Seconds",-1);
if(t_cUser.CompareNoCase("inquiry")==0)
t_cConnect="UID=inquiry;PWD=inquiry;DSN=AWIMS";
else
t_cConnect.Format("UID=%s;PWD=%s;DSN=AWIMS",t_cUser,t_cPass);
try {
t_PickDB.OpenEx(t_cConnect,CDatabase::noOdbcDialog | CDatabase::useCursorLib);
}
// Catch any DB exceptions that may have been thrown by the Open call
catch (CDBException* e) {
AfxMessageBox(e->m_strError,MB_ICONEXCLAMATION);
return 1;
}
rsPickQueue.m_pDatabase=&(t_PickDB);
rsPickQueue.m_strSort="REQUEST_TIME";
if(!rsPickQueue.Open(CRecordset::snapshot, NULL, CRecordset::none)) {
AfxMessageBox(IDP_FAILED_OPEN_DATABASE);
return 2;
}
---> everything works up to this point of the thread "initialization"
// Switch to the Pick pane and activate the pick tab
Fails on this call with an unhandled exception
|
---> ((MainFrame *)(::AfxGetMainWnd()))->m_wndSplitter.SetActivePane(0, 0);
CView *view = ((CFrameWnd *) AfxGetMainWnd())->GetActiveView();
if(view->IsKindOf(RUNTIME_CLASS(CPickTabView))) {
((CPickTabView *)view)->SetActiveTab(0);
}
// t->pPick is a pointer to the view which is a tab on the CPickTabView
(((CPickTabView *)view)->t_pPick)->m_PickAVI.Open(IDR_AWIMS);
while(TRUE) {
dwResult=WaitForSingleObject(m_hEventStop,(t_iRefresh * 1000));
if(dwResult == WAIT_TIMEOUT) {
(((CPickTabView *)view)->t_pPick)->m_PickAVI.Play(0,-1,-1);
::Beep(5000,100);
::Sleep(5000);
rsPickQueue.Requery();
while(!rsPickQueue.IsEOF()) {
rsPickQueue.MoveNext();
}
(((CPickTabView *)view)->t_pPick)->m_PickAVI.Stop();
}
else {
rsPickQueue.Close();
(((CPickTabView *)view)->t_pPick)->m_PickAVI.Close();
return 0;
}
}
}
Steven M. McNeese
[email protected]
Re: Accessing CView controls from worker thread
I think the problem is caused because you are not allowed to pass CWnd between threads, but HWNDs.
Re: Accessing CView controls from worker thread
I agree with Bogdan. Use HWND!!!
As well, make sure the two threads can't access the listbox at the same time
Re: Accessing CView controls from worker thread
Well, I did it a little different. When adding a CView as a tab to my tab control, it returns a pointer the the view. I keep this pointer as a member of my main App class. Then I reference the controls on the view like this:
CAWIMSApp* pApp = (CAWIMSApp*)AfxGetApp();
((CPick *)pApp->t_pPick)->m_PickAVI.Play(0,-1,-1);
((CPick *)pApp->t_pPick)->m_ListPick.DeleteAllItems();
.
.
.
etc.
Works great! Though I was going to have to use CSemaphor between to two threads, but I have not run into any problems with that either. The worker thread is constantly refreshing the listctrl and the main app thread can select items within the listctrl and delete them, move them, etc. Not sure if I understand that based on what I have read about threads but, If it aint broke don't fix it....yet!
Steven M. McNeese
[email protected]