C++ Builder 高手進階

來源:互聯網
上載者:User

 

(五)用BCB編寫多線程應用程式

 

隨著Windows系統的全球性普及,多線程技術已越來越多地運用到許多軟體設計中。使用多線程技術可全面提高應用程式的執行效率。以前為了實現多線程編程,基本上都是調用一系列的API函數,如CreateThread、ResumeThread等,不容易控制,還容易出錯。在使用BCB以後,我才發現原來編寫多線程程式也可以如此簡單!BCB為我們提供了強大的TThread類,從而使得多線程編程變得非常簡便易用。下面請跟我一起開始我們的BCB多線程編程之旅。

1. 建立多線程程式:

首先,我介紹一下BCB中編寫多線程程式的具體步驟。

在C++Builder IDE環境下選擇菜單FileNew,在New欄中選中Thread Object,按OK,接下來彈出輸入框,輸入TThread對象子類的名字NewThread,這樣C++Builder自動為你建立了一個名為TNewThread的TThread子類。下面是TNewThread的部分源碼:

__fastcall NewThread::MyThread(bool CreateSuspended)

: TThread(CreateSuspended)

{//建構函式,可用來初始化一些資訊

}

void __fastcall NewThread::Execute()

{

//多線程程式的核心,用來執行相關多線程操作

}

   BCB中的Execute()函數是我們要線上程中實現的任務代碼所在地。使用多線程時,動態建立一個TNewThread 對象,在建構函式中使用Resume()方法,具體執行的代碼使用Execute()方法重載的代碼。如果想建立更多的線程,只需要建立需要數量的TNewThread 而已。

通過以上步驟我們基本實現了在程式中如何建立一個線程,並使程式實現了多線程應用。但是,多線程應用的實現,並不是一件簡單的工作,還需要考慮很多使多個線程能在系統中共存、互不影響的因素。比如,程式中公開變數的訪問、資源的分配,如果處理不當,不僅線程會死結陷入混亂,甚至可能會造成系統崩潰。總的來講,在多線程編程中要注意共用對象和資料的處理,不能忽視。因此,下面我們要講的就是多線程中常見問題:

2. 多線程中VCL對象的使用

我們都知道,C++Builder編程是建立在VCL類庫的基礎上的。在程式中經常需要訪問VCL對象的屬性和方法。不幸的是,VCL類庫並不保證其中對象的屬性和方法是線程訪問安全的(Thread_safe),訪問VCL對象的屬性或調用其方法可能會訪問到不被別的線程所保護的記憶體地區而產生錯誤。因此,TThread對象提供了一個Synchronize方法,當需要線上程中訪問VCL對象屬性或調用方法時,通過Synchronize方法來訪問屬性或調用方法就能避免衝突,使各個線程之間協調而不會產生意外的錯誤。如下所示:

void __fastcall TNewThread::PushTheButton(void)

{

Button1->Click();

}

void __fastcall TNewThread::Execute()

{

...

Synchronize((TThreadMethod)PushTheButton);

...

}

對Button1-〉Click()方法的調用就是通過Synchronize()方法來實現的,它可以自動避免發生多線程存取違規。在C++Builder中,雖然有一些VCL對象也是線程訪問安全的(如TFont、TPen、TBrush等),可以不用Sychronize()方法對它們的屬性方法進行訪問調用以提高程式效能,但是,對於更多的無法確定的VCL對象,還是強烈建議使用Synchronize()方法確保程式的可靠性。

C++ Builder 高手進階(五)用BCB編寫多線程應用程式(2) 3. 多線程中公用資料的使用

程式設計中難免要在多個線程中共用資料或者對象。為了避免在多線程中因為同時訪問了公用資料區塊而造成災難性的後果,我們需要對公用資料區塊進行保護,直到一個線程對它的訪問結束為止。這可以通過臨界地區(Critical Section)的使用來實現,所幸的是在C++Builder中,給我們提供了一個TCriticalSection對象來進行臨界地區的劃定。該對象有兩個方法,Acquire()和Release()。它設定的臨界地區可以保證一次只有一個線程對該地區進行訪問。如下例所示:

class TNewThread : public TThread

{

...

private:

TCriticalSection pLockX;

int x;

float y;

...

};

void __fastcall TNewThread::Execute()

{

...

pLockX->Acquire();

x++;

y=sin(x);

pLockX->Release();

...

}

這樣,對公開變數x,y的訪問就通過全域TCriticalSection 對象保護起來,避免了多個線程同時訪問的衝突。

4. 多線程間的同步

當程式中多個線程同時運行,難免要遇到使用同一系統資源,或者一個線程的運行要依賴另一個線程的完成等等,這樣需要線上程間進行同步的問題。由於線程同時運行,無法從程式本身來決定啟動並執行先後快慢,使得線程的同步看起來很難實現。所幸的是Windows系統是多任務作業系統,系統核心為我們提供了事件(Event)、Mutex、號誌(semaphore)和計時器4種對象來控制線程間的同步。在C++Builder中,為我們提供了用於建立Event的TEvent 對象供我們使用。

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

其實直接用Windows API函數也可以很方便地實現事件(Event)、訊號(semaphore)控制技術。尤其是C++Builder,在調用Windows API方面有著其它語言無可比擬的優勢。所用的函數主要有:CreateSemaphore()、CreateEvent()、WaitForSingleObject()、ReleaseSemaphore()、SetEvent()等等。

< TD>

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.