對 ODBC 類的多線程支持有一些限制。 因為這些類包裝了 ODBC API,所以對 ODBC 類的多線程支持僅限于對它們所依賴的組件的多線程支持。 例如,許多 ODBC 驅(qū)動程序都不是線程安全的;因此如果 MFC ODBC 類和這樣的一種驅(qū)動程序一起使用,這些類也不是線程安全的。 應(yīng)該驗證您的特定驅(qū)動程序是否是線程安全的。
創(chuàng)建多線程應(yīng)用程序時,使用多線程處理同一對象一定要非常小心。 例如,在兩個線程中使用同一 CRecordset 對象在檢索數(shù)據(jù)時可能會引發(fā)問題;一個線程中的獲取操作可能會覆蓋在另一個線程中獲取的數(shù)據(jù)。 MFC ODBC 類在單獨的線程中的更常見用法是在這些線程中共享一個打開的 CDatabase 對象以使用同一個 ODBC 連接,而在每一個線程中都有單獨的 CRecordset 對象。 注意不要將未打開的 CDatabase 對象傳遞給另一個線程中的 CRecordset 對象。
如果必須用多線程處理同一對象,則應(yīng)該執(zhí)行適當(dāng)?shù)耐綑C(jī)制,如臨界區(qū)。 請注意對某些操作(如 Open 操作)沒有提供保護(hù)。 您應(yīng)該確保這些操作不會被單獨的線程并行調(diào)用。
CRecordset 中的CTime變量和bug
如果使用了VC++6.0 Wizard重載CRecordset,并且指定的數(shù)據(jù)源中有時間變量,那么VC6將生成一個CTime變量,但是這個變量在構(gòu)造函數(shù)中并不會被初始化,因此,必須手工添加,如:m_tTime = 0,否則,程序在運(yùn)行過程中通常在執(zhí)行void YourODBCTable::DoFieldExchange(CFieldExchange* pFX)時,在RFX_Date(pFX, _T("[tTIME]"), m_tTIME)處發(fā)生訪問越界錯誤,更有甚者,當(dāng)程序的復(fù)雜度較大時可能發(fā)生在一些不確定的區(qū)域,為程序調(diào)試帶來巨大的難度。導(dǎo)致發(fā)生問題的原因是m_tTime可能是負(fù)值,所以調(diào)用GetLocalTm(NULL)->tm_year時發(fā)生訪問越界的錯誤。
如果必須用多線程處理同一對象,則應(yīng)該執(zhí)行適當(dāng)?shù)耐綑C(jī)制,如臨界區(qū)。 請注意對某些操作(如 Open 操作)沒有提供保護(hù)。 您應(yīng)該確保這些操作不會被單獨的線程并行調(diào)用。
CRecordset 中的CTime變量和bug
如果使用了VC++6.0 Wizard重載CRecordset,并且指定的數(shù)據(jù)源中有時間變量,那么VC6將生成一個CTime變量,但是這個變量在構(gòu)造函數(shù)中并不會被初始化,因此,必須手工添加,如:m_tTime = 0,否則,程序在運(yùn)行過程中通常在執(zhí)行void YourODBCTable::DoFieldExchange(CFieldExchange* pFX)時,在RFX_Date(pFX, _T("[tTIME]"), m_tTIME)處發(fā)生訪問越界錯誤,更有甚者,當(dāng)程序的復(fù)雜度較大時可能發(fā)生在一些不確定的區(qū)域,為程序調(diào)試帶來巨大的難度。導(dǎo)致發(fā)生問題的原因是m_tTime可能是負(fù)值,所以調(diào)用GetLocalTm(NULL)->tm_year時發(fā)生訪問越界的錯誤。
這個問題與微軟的BUG有關(guān)(具體不詳),但是如果我們都有一個良好的編程習(xí)慣,那這個BUG就沒有危害,當(dāng)然,我這個帖子也就沒有了,呵呵~