在C Builer中多執行緒的實現

2021-05-10 04:15:06 字數 3590 閱讀 4761

還在dos時代,人們就在尋求一種多工的實現。於是出現了tsr型別的後台駐留程式,比較有代表性的有side kick、vsafe等優秀的tsr程式,這類程式的出現和應用確實給使用者使用計算機帶來了極大的方便,比如side kick,我們程式設計可以在不用進編輯程式的狀態下,一邊編輯源程式,一邊編譯執行,非常方便。但是,dos單任務作業系統的致命缺陷注定了在dos下不可能開發出真正的多工程式。進入windows3.1時代,這種情況依然沒有根本的改變,一次應用只能做一件事。比如資料庫查詢,除非應用編得很好,在查詢期間整個系統將不響應使用者的輸入。

進入了windows nt和windows 9x時代,情況就有了徹底的改觀,作業系統從真正意義上實現了多工(嚴格地說,win9x還算不上)。乙個應用程式,在需要的時候可以有許多個執行執行緒,每個執行緒就是乙個小的執行程式,作業系統自動使各個執行緒共享cpu資源,確保任一線程都不能使系統死鎖。這樣,在程式設計的時候,可以把費時間的任務移到後台,在前台用另乙個執行緒接受使用者的輸入。對那些對實時性要求比較高的程式設計任務,如網路客戶服務、序列通訊等應用時,多執行緒的實現無疑大大地增強了程式的可用性和穩固性。

在windows nt和windows 9x中,多執行緒的程式設計實現需要呼叫一系列的api函式,如createthread、resumethread等,比較麻煩而且容易出錯。我們使用inprise公司的新一代rad開發工具c++builder,可以方便地實現多執行緒的程式設計。與老牌rad工具visual basic和delphi比,c++builer不僅功能非常強大,而且它的程式語言是c++,對於系統開發語言是c的windows系列作業系統,它具有其它程式語言無可比擬的優勢。利用c++builder提供的tthread物件,多執行緒的程式設計變得非常簡便易用。那麼,如何實現呢?且待我慢慢道來,讓你體會一下多執行緒的強大功能。

1. 建立多執行緒程式:

首先,先介紹一下實現多執行緒的具體步驟。在c++builder中雖然用tthread物件說明了執行緒的概念,但是tthread物件本身並不完整,需要在tthread下新建其子類,並過載execute方法來使用執行緒物件。在c++builder下可以很方便地實現這一點。

在c++builder ide環境下選擇選單file|new,在new欄中選中thread object,按ok,接下來彈出輸入框,輸入tthread物件子類的名字mythread,這樣c++builder自動為你建立了乙個名為tmythread的tthread子類。同時編輯器中多了乙個名為unit2.cpp的單元,這就是我們建立的tmythread子類的原碼,如下:

#include

#pragma hdrstop

#include 「unit2.h」

#pragma package(smart_init)

//---------------------

// important: methods and properties of objects in vcl can only be

// used in a method called using synchronize, for example:

//// synchronize(updatecaption);

//// where updatecaption could look like:

//// void __fastcall mythread::updatecaption()

// //--------------------

__fastcall mythread::mythread(bool createsuspended)

: tthread(createsuspended)

//--------------------

void __fastcall mythread::execute()

//---------------------

以上我們初步地實現了在程式中建立乙個自定義的執行緒,並使程式實現了多執行緒應用。但是,多執行緒應用的實現,並不是一件簡單的工作,還需要考慮很多使多個執行緒能在系統中共存、互不影響的因素。比如,程式中公共變數的訪問、資源的分配,如果處理不當,不僅執行緒會死鎖陷入混亂,甚至可能會造成系統崩潰。總的來講,在多執行緒程式設計中要注意共享物件和資料的處理,不能忽視。因此,下面我們要講的就是多執行緒中常見問題:

void __fastcall tmythread::pushthebutton(void)

void __fastcall tmythread::execute()

對button1-〉click()方法的呼叫就是通過synchronize()方法來實現的,它可以自動避免發生多執行緒訪問衝突。在c++builder中,雖然有一些vcl物件也是執行緒訪問安全的(如tfont、tpen、tbrush等),可以不用sychronize()方法對它們的屬性方法進行訪問呼叫以提高程式效能,但是,對於更多的無法確定的vcl物件,還是強烈建議使用synchronize()方法確保程式的可靠性。

3. 多執行緒中公共資料的使用

程式設計中難免要在多個執行緒中共享資料或者物件。為了避免在多執行緒中因為同時訪問了公共資料塊而造成災難性的後果,我們需要對公共資料塊進行保護,直到乙個執行緒對它的訪問結束為止。這可以通過臨界區域(critical section)的使用來實現,所幸的是在c++builder中,給我們提供了乙個tcriticalsection物件來進行臨界區域的劃定。該物件有兩個方法,acquire()和release()。它設定的臨界區域可以保證一次只有乙個執行緒對該區域進行訪問。如下例所示:

class mythread : public tthread

;void __fastcall mythread::execute()

這樣,對公共變數x,y的訪問就通過全域性tcriticalsection 物件保護起來,避免了多個執行緒同時訪問的衝突。

4. 多執行緒間的同步

當程式中乙個執行緒的執行要等待一項特定的操作的完成而不是等待乙個特定的執行緒完成時,我們就可以很方便地用tevent物件來實現這個目標。首先建立乙個全域性的tevent物件作為所有執行緒可監測的標誌。當乙個執行緒完成某項特定的操作時,呼叫tevent物件的setevent()方法,這樣將設定這個標誌,其他的執行緒可以通過監測這個標誌獲知操作的完成。相反,要取消這個標誌,可以呼叫resetevent()方法。在需要等待操作完成的執行緒中使用waitfor()方法,將一直等待這個標誌被設定為止。注意waitfor()方法的引數是等待標誌設定的時間,一般用infinite表示無限等待事件的發生,如果其它執行緒執行有誤,很容易使這個執行緒死住(等待乙個永不發生的事件)。

其實直接用windows api函式也可以很方便地實現事件(event)、訊號燈(semaphore)控制技術。尤其是c++builder,在呼叫windows api方面有著其它語言無可比擬的優勢。所用的函式主要有:createsemaphore()、createevent()、waitforsingleobject()、releasesemaphore()、setevent()等等,這裡就不贅述了。

本文結合inprise(borland)公司開發的強大的rad工具c++builder的程式設計,對windows下的多執行緒程式設計作了比較全面的介紹。其實多執行緒的實現並不神秘,看了本文,你也可以編出自己的多執行緒程式,真正體會多工作業系統的威力。

附:本文是本人在使用c++builder一年來的一些實踐體會。在完成自己的專案的同時,發現對多執行緒的程式設計一般的書籍都介紹得比較少,而實際應用中,多執行緒程式設計又是如此的重要,因此,本文通過對多執行緒程式設計比較全面的介紹,願能達到拋磚引玉之效。

在VB中實現多執行緒

功能 建立多執行緒類,用於初始化執行緒。類名 cls thread 呼叫方法 1.宣告執行緒類物件變數 dim mythread as cls thread 2.呼叫形式 with mythread initialize addressof 自定義過程或函式名 初始化執行緒 threadenable...

在SpringBoot框架中實現多執行緒的方式

1.新增配置類 configuration enableasync public class asynctaskconfig implements asyncconfigurer override public asyncuncaughtexceptionhandler getasyncuncaug...

在 DOS 下實現多執行緒

在 dos 下實現多執行緒 程式在 turbo c 3.0 下除錯通過,採用了最簡單的時間片輪轉法,實現了多執行緒的系統,程式盡量採用了最簡潔的技術來實現多工的系統,主要使用到了c標準庫中的setjmp和longjmp兩個函式,程式絕大部分都是採用c c 語言書寫,但是仍然不可避免的採用了三句內嵌彙...