C 多執行緒程式設計(一)問題的提出

2021-09-30 16:13:31 字數 4690 閱讀 8584

多執行緒程式設計之一——問題提出

一、問題的提出

編寫乙個耗時的單執行緒程式:

新建乙個基於對話方塊的應用程式singlethread,在主對話方塊idd_singlethread_dialog新增乙個按鈕,id為idc_sleep_six_second,標題為「延時6秒」,新增按鈕的響應函式,**如下:

編譯並執行應用程式,單擊「延時6秒」按鈕,你就會發現在這6秒期間程式就象「宕機」一樣,不在響應其它訊息。為了更好地處理這種耗時的操作,我們有必要學習——多執行緒程式設計。 

二、多執行緒概述

三、win32 api對多執行緒程式設計的支援

win32 提供了一系列的api函式來完成執行緒的建立、掛起、恢復、終結以及通訊等工作。下面將選取其中的一些重要函式進行說明。

1、
該函式在其呼叫程序的程序空間裡建立乙個新的執行緒,並返回已建執行緒的控制代碼,其中各引數說明如下:

如果建立成功則返回執行緒的控制代碼,否則返回null。

2、dword suspendthread(handle hthread);
該函式用於掛起指定的執行緒,如果函式執行成功,則執行緒的執行被終止。

3、dword resumethread(handle hthread);
該函式用於結束執行緒的掛起狀態,執行執行緒。

4、void exitthread(dword dwexitcode);
5、bool terminatethread(handle hthread,dword dwexitcode);
一般情況下,執行緒執行結束之後,執行緒函式正常返回,但是應用程式可以呼叫terminatethread強行終止某一線程的執行。各引數含義如下:

使用terminatethread()終止某個執行緒的執行是不安全的,可能會引起系統不穩定;雖然該函式立即終止執行緒的執行,但並不釋放執行緒所占用的資源。因此,一般不建議使用該函式。

6、
該函式將一條訊息放入到指定執行緒的訊息佇列中,並且不等到訊息被該執行緒處理時便返回。

呼叫該函式時,如果即將接收訊息的執行緒沒有建立訊息迴圈,則該函式執行失敗。

四、win32 api多執行緒程式設計例程

例程1 multithread1

建立乙個基於對話方塊的工程multithread1,在對話方塊idd_multithread1_dialog中加入兩個按鈕和乙個編輯框,兩個按鈕的id分別是idc_start,idc_stop ,標題分別為「啟動」,「停止」,idc_stop的屬性選中disabled;編輯框的id為idc_time ,屬性選中read-only;

在multithread1dlg.**件中新增執行緒函式宣告:

void threadfunc();
注意,執行緒函式的宣告應在類cmultithread1dlg的外部。 在類cmultithread1dlg內部新增protected型變數:
handle hthread;

dword threadid;

分別代表執行緒的控制代碼和id。

在multithread1dlg.cpp檔案中新增全域性變數m_brun :

volatile bool m_brun;
m_brun 代表執行緒是否正在執行。

你要留意到全域性變數 m_brun 是使用 volatile 修飾符的,volatile 修飾符的作用是告訴編譯器無需對該變數作任何的優化,即無需將它放到乙個暫存器中,並且該值可被外部改變。對於多執行緒引用的全域性變數來說,volatile 是乙個非常重要的修飾符。

編寫執行緒函式:

該執行緒函式沒有引數,也不返回函式值。只要m_brun為true,執行緒一直執行。

雙擊idc_start按鈕,完成該按鈕的訊息函式:

雙擊idc_stop按鈕,完成該按鈕的訊息函式:
編譯並執行該例程,體會使用win32 api編寫的多執行緒。   

例程2 multithread2

該執行緒演示了如何傳送乙個乙個整型的引數到乙個執行緒中,以及如何等待乙個執行緒完成處理。

建立乙個基於對話方塊的工程multithread2,在對話方塊idd_multithread2_dialog中加入乙個編輯框和乙個按鈕,id分別是idc_count,idc_start ,按鈕控制項的標題為「開始」;

在multithread2dlg.**件中新增執行緒函式宣告:

void threadfunc(int integer);
注意,執行緒函式的宣告應在類cmultithread2dlg的外部。

在類cmultithread2dlg內部新增protected型變數:

handle hthread;

dword threadid;

分別代表執行緒的控制代碼和id。

開啟classwizard,為編輯框idc_count新增int型變數m_ncount。在multithread2dlg.cpp檔案中新增:

雙擊idc_start按鈕,完成該按鈕的訊息函式:
順便說一下waitforsingleobject函式,其函式原型為:
dword waitforsingleobject(handle hhandle,dword dwmilliseconds);
當在某一線程中呼叫該函式時,執行緒暫時掛起,系統監視hhandle所指向的物件的狀態。如果在掛起的dwmilliseconds毫秒內,執行緒所等待的物件變為有訊號狀態,則該函式立即返回;如果超時時間已經到達dwmilliseconds毫秒,但hhandle所指向的物件還沒有變成有訊號狀態,函式照樣返回。引數dwmilliseconds有兩個具有特殊意義的值:0和infinite。若為0,則該函式立即返回;若為infinite,則執行緒一直被掛起,直到hhandle所指向的物件變為有訊號狀態時為止。

本例程呼叫該函式的作用是按下idc_start按鈕後,一直等到執行緒返回,再恢復idc_start按鈕正常狀態。編譯執行該例程並細心體會。

例程3 multithread3

傳送乙個結構體給乙個執行緒函式也是可能的,可以通過傳送乙個指向結構體的指標引數來完成。先定義乙個結構體:

建立執行緒時

createthread(null,0,threadfunc,pmytype,…);
在threadfunc函式內部,可以使用「強制轉換」:

int intvalue=((pmytype)lpvoid)->firstargu;

long lon**alue=((pmytype)lpvoid)->seconddargu;

……

例程3 multithread3將演示如何傳送乙個指向結構體的指標引數。

建立乙個基於對話方塊的工程multithread3,在對話方塊idd_multithread3_dialog中加入乙個編輯框idc_millisecond,乙個按鈕idc_start,標題為「開始」 ,乙個進度條idc_progress1;

開啟classwizard,為編輯框idc_millisecond新增int型變數m_nmillisecond,為進度條idc_progress1新增cprogressctrl型變數m_ctrlprogress;

在multithread3dlg.**件中新增乙個結構的定義:

struct threadinfo

;

執行緒函式的宣告:
uint threadfunc(lpvoid lpparam);
注意,二者應在類cmultithread3dlg的外部。

在類cmultithread3dlg內部新增protected型變數:

handle hthread;

dword threadid;

分別代表執行緒的控制代碼和id。

在multithread3dlg.cpp檔案中進行如下操作:

定義公共變數 threadinfo info;

雙擊按鈕idc_start,新增相應訊息處理函式:

在函式bool cmultithread3dlg::oninitdialog()中新增語句:
新增執行緒處理函式:uint threadfunc(lpvoid lpparam)
順便補充一點,如果你在void cmultithread3dlg::onstart() 函式中新增/* */語句,編譯執行你就會發現進度條不進行重新整理,主線程也停止了反應。什麼原因呢?這是因為waitforsingleobject函式等待子執行緒(threadfunc)結束時,導致了執行緒死鎖。因為waitforsingleobject函式會將主線程掛起(任何訊息都得不到處理),而子執行緒threadfunc正在設定進度條,一直在等待主線程將重新整理訊息處理完畢返回才會檢測通知事件。這樣兩個執行緒都在互相等待,死鎖發生了,程式設計時應注意避免。 

例程4 multithread4

該例程測試在windows下最多可建立執行緒的數目。

建立乙個基於對話方塊的工程multithread4,在對話方塊idd_multithread4_dialog中加入乙個按鈕idc_test和乙個編輯框idc_count,按鈕標題為「測試」 , 編輯框屬性選中read-only;

在multithread4dlg.cpp檔案中進行如下操作:

新增公共變數

volatile bool m_brunflag=true;
該變數表示是否還能繼續建立執行緒。

新增執行緒函式:

只要 m_brunflag 變數為true,執行緒一直執行。

雙擊按鈕idc_test,新增其響應訊息函式:

(未完待續)

C 多執行緒程式設計(一)

使用c 可以讓程式交替執行兩個程式,基於程序的多工處理和同一程式片段的併發執行。此外,筆者在進行多執行緒程式設計中使用的是linux作業系統。首先,可以建立乙個執行緒。include pthread create thread,attr,start routine,arg thread是指向執行緒識...

執行時動態建立報表(一)問題提出

很多時候,客戶可能隨時提出新的報表要求,我們不得不再修改 建立新的報表。因此我們會想,可不可以設計乙個架構,只修改後台的定義檔案,客戶端就可以根據定義檔案展現不同的報表。網上已經有了很多利用ms 的reportviewer動態建立報表的介紹。我在研究這些文章後覺得,完全可以實現上面的設想。目前已經設...

C 多執行緒程式設計

一 thread 基礎 程序 當乙個程式開始執行時,它就是乙個程序,程序包括執行中的程式和程式所使用到的記憶體和系統資源。而乙個程序又是由多個執行緒所組成的。執行緒 執行緒是程式中的乙個執行流,每個執行緒都有自己的專有暫存器 棧指標 程式計數器等 但 區是共享的,即不同的執行緒可以執行同樣的函式 方...