在開發的過程經常需要處理這樣一個情況: 進行一個比較耗時的操作, 例如從網絡上下載一個大文件, 或者從數據庫中讀上萬條記錄, 如果不採取一些優化措施直接進行操作的話, 在執行操作的過程中, 窗口消息循環就會被阻塞掉, 這時, 用戶在窗口上進行點擊、或者移動窗口等操作均會無效,用戶甚至會誤以爲程序死掉了。爲了解決這種情況,即在耗時的操作正在執行的過程中,讓用戶仍舊可以流暢地操作窗口,一些朋友會使用多線程來處理,即把比較耗時的操作放到多線程去處理,然後把處理結果通過多線程同步的方式更新到界面上。
用多線程沒有什麼不好,但是在處理多線程同步時一般都比較痛苦 :) ---- 因爲當程序複雜一點的時候,比較容易出錯,而且給調試也帶來了一定的困難,特別是初始者,處理不好多線程的同步情況,會給系統留下陷阱,出錯時也不容易找出原因。
像讀數據庫,從網絡上下載文件等這樣的例子來說,看似耗時的操作實際上是可以分片來進行的,因爲從數據庫中讀100條記錄,或者從網絡上下載1k字節都會很快處理完,因此,我們可以使用類似下面的方法而避免使用多線程,下面是下載一個大文件的例子:
CHttpFile *pFile =m_pHttp->OpenRequest(CHttpConnection::HTTP_VERB_GET,
strFile, NULL, 1, NULL, NULL, m_dwHttpRequestFlags);
CStdioFile csf;
csf.Open(str+".upg",CFile::modeCreate|CFile::modeWrite | CFile::typeBinary
| CFile::shareDenyWrite);
try{
pFile->SendRequest();
}
catch(...)
{
...
}
...
//從網絡下載2K個字節放進緩衝區
while((n=pFile->Read(buf,2048))>0)
{
//更新界面上的進度條顯示
dwReadCount += n;
m_ctlProgress.SetPos(100*dwReadCount/dwLen);
//讓消息循環處理10條消息
for(int i=0;i<10;i++)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//把下載到的數據寫入文件
csf.Write(buf,n);
}
pFile->Close();
cst->Close();
讀數據庫的操作也可以類似地處理,例如要從數據庫中讀1萬條記錄顯示到列表中,可以採用每次讀100條記錄,然後讓消息循環處理10條消息(或者更多,視情況而定),再繼續讀下100條記錄,直至讀完1萬條記錄爲止。