在DAO多线程处理中,有许多局限性,所以我设计了这么一个类,通过GUI线程来使用DAO的强制调用。在类中使用了GUI的消息队列,所有进入到CMultiDAORecordset的调用都被迫使用AfxGetThread()来检查当前的线程。GUI线程指针是放在InitInstance的首端,如果在GUI线程中,引入的调用请求不在运行,那么CMultiDAORecordSet就会发送一个WM_MULTIDAOMESSAGE消息给AfxGetMainWnd()(在Mainfrm.cpp中)。Mainfrm接受到这个消息,线程也就要再运行一次,这个时候,消息已经接受了,基类CDaoRecordset也就得到了调用。所以你的类是从CMultiDAORecordset继承的,而不是CDaoRecordset,如下:
class CMySet : public CMultiDaoRecordSet
在相应的CPP文件中也应该改一下:
IMPLEMENT_DYNAMIC(CMySet, CMultiDaoRecordSet)
CMySet::CMySet (CDaoDatabase* pdb) : CMultiDaoRecordSet(pdb)
为了处理接受到的WM_MULTIDAOMESSAGE消息,下面的代码还应该加在MainFrm中:
在MainFrm.h文件中加:
#ifdef MAINFRAME_CPP UINT WM_MULTIDAOMESSAGE = RegisterWindowMessage("WM_MULTIDAOMESSAGE"); #else extern UINT WM_MULTIDAOMESSAGE; #endif afx_msg LONG OnMultiDaoMessage( UINT uParam, LONG lParam); 在MainFrm.cpp文件中加: #define MAINFRAME_CPP #include "MutliDaoRecordset.h" //added to the message map BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_REGISTERED_MESSAGE(WM_MULTIDAOMESSAGE, OnMultiDaoMessage) END_MESSAGE_MAP() //this function added LONG CMainFrame::OnMultiDaoMessage( UINT uParam, LONG lParam) { //jtm //based on switch, perform operation... CMultiDaoRecordSet *pSet = (CMultiDaoRecordSet *)lParam; LONG lRet = 0; CString cRet = ""; COleVariant cVar; try { //jtm-------debug-------------------------------------- CString cTraceMessage = cDAOMessageArray[uParam]; cTraceMessage += "\n"; TRACE(cTraceMessage); //jtm-------debug-------------------------------------- switch(uParam) { case MultiDaoOpen: pSet->Open(); break; case MultiDaoClose: pSet->Close(); break; case MultiDaoIsOpen: lRet = (LONG)pSet->IsOpen(); break; case MultiDaoIsBOF: lRet = (LONG)pSet->IsBOF(); break; case MultiDaoIsEOF: lRet = (LONG)pSet->IsEOF(); break; case MultiDaoIsDeleted: lRet = (LONG)pSet->IsDeleted(); break; case MultiDaoIsFieldDirty: lRet = (LONG)pSet->IsFieldDirty(pSet->pParam1); break; case MultiDaoIsFieldNull: lRet = (LONG)pSet->IsFieldNull(pSet->pParam1); break; case MultiDaoIsFieldNullable: lRet = (LONG)pSet->IsFieldNullable(pSet->pParam1); break; case MultiDaoGetName: cRet = pSet->GetName(); lRet = (LONG)&cRet; break; case MultiDaoGetType: lRet = (LONG)pSet->GetType(); break; case MultiDaoGetEditMode: lRet = (LONG)pSet->GetEditMode(); break; case MultiDaoGetLastModifiedBookmark: cVar = pSet->GetLastModifiedBookmark(); lRet = (LONG)&cVar; break; case MultiDaoGetRecordCount: lRet = (LONG)pSet->GetRecordCount(); break; case MultiDaoMoveNext: pSet->MoveNext(); break; case MultiDaoMovePrev: pSet->MovePrev(); break; case MultiDaoMoveFirst: pSet->MoveFirst(); break; case MultiDaoMoveLast: pSet->MoveLast(); break; case MultiDaoMove: pSet->Move(*(LONG *)pSet->pParam1); break; case MultiDaoFindNext: lRet = (LONG)pSet->FindNext(*(LPCTSTR *)pSet->pParam1); break; case MultiDaoFindPrev: lRet = (LONG)pSet->FindPrev(*(LPCTSTR*)pSet->pParam1); break; case MultiDaoFindFirst: lRet = (LONG)pSet->FindFirst(*(LPCTSTR *)pSet->pParam1); break; case MultiDaoFindLast: lRet = (LONG)pSet->FindLast(*(LPCTSTR *)pSet->pParam1); break; case MultiDaoFind: lRet = (LONG)pSet->Find(*(LONG *)pSet->pParam1, *(LPCTSTR*)pSet->pParam2); break; case MultiDaoGetBookmark: cVar = pSet->GetBookmark(); lRet = (LONG)&cVar; break; case MultiDaoSetBookmark: pSet->SetBookmark(*(COleVariant*)pSet->pParam1); break; case MultiDaoAddNew: pSet->AddNew(); break; case MultiDaoEdit: pSet->Edit(); break; case MultiDaoUpdate: pSet->Update(); break; case MultiDaoDelete: pSet->Delete(); break; case MultiDaoCancelUpdate: pSet->CancelUpdate(); break; case MultiDaoRequery: pSet->Requery(); break; } } catch (CDaoException *e) { TRACE("Database Multithread Operation Failed%s\n", e->m_pErrorInfo->m_strDescription); } return lRet; } |
public: CWinThread *pGUIThread; And this to the constructor in the app .cpp file: CMyApp::CMyApp() { pGUIThread = AfxGetThread(); } |