| 導購 | 订阅 | 在线投稿
分享
 
 
當前位置: 王朝網路 >> delphi >> WIN32下DELPHI中的多線程【同步1】(四)
 

WIN32下DELPHI中的多線程【同步1】(四)

2006-12-11 21:23:45  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
 
  線程的同步

   在使用的時候,多線程最讓人頭疼的也許就是同步了。

   如果你的線程只是完成一件並不需要訪問線程對象外部資源的工作,在這種情況下,線程互相之間不需要進行通信,此時Windows的運行性能最好。但是,線程很少能夠在所有的時間都獨立地進行操作。通常情況下,要生成一些線程來處理某個任務。當這個任務完成時,另一個線程必須了解這個情況。

   系統中的所有線程都必須擁有對各種系統資源的訪問權,這些資源包括內存堆棧,文件,窗口和許多其他資源。如果一個線程需要獨占對資源的訪問權,那麽其他線程就無法完成它們的工作。反過來說,也不能讓任何一個線程在任何時間都能訪問所有的資源。如果在一個線程從內存塊中讀取數據時,另一個線程卻想要將數據寫入同一個內存塊,那麽這就像你在讀一本書時另一個人卻在修改書中的內容一樣。這樣,書中的內容就會被搞得亂七八糟,結果什麽也看不清楚。

   線程需要在下面兩種情況下互相進行通信:

   • 當有多個線程訪問共享資源而不使資源被破壞時。

   • 當一個線程需要將某個任務已經完成的情況通知另外一個或多個線程時。

   線程的同步包括許多方面的內容,Windows提供了許多方法,可以非常容易地實現線程的同步。但是,要想隨時了解一連串的線程想要做什麽,那是非常困難的。我們的頭腦的工作不是異步的,我們希望以一種有序的方式來思考許多事情,每次前進一步。不過多線程環境不是這樣運行的。你幾乎無法完全知道目標系統中存在多少線程,也不知道他們處在什麽狀態下,更不知道他們要幹什麽。

  用戶方式下的線程同步

  1、互鎖函數

  在MSDN關于同步函數的幫助文檔中,你會看到大量的互鎖函數。他們大多以Interlocked****的名字存在。互鎖函數運行在用戶模式。它能保證當一個線程訪問一個變量時,其它線程無法訪問此變量,以確保變量值的唯一性。這種訪問方式被稱爲原子訪問。

  常用的互鎖函數及其功能見如下列表:

  

  

   函數

   參數和功能

  

  

   InterlockedIncrement

   參數爲PLONG類型。此函數使一個LONG變量增1

  

  

   InterlockedDecrement

   參數爲PLONG類型。此函數使一個LONG變量減1

  

  

   InterlockedExchangeAdd

   參數1爲PLONG類型,參數2爲LONG類型。此函數將參數2賦給參數1指向的值

  

  

   InterlockedExchange

   參數1爲PLONG類型,參數2爲LONG類型。此函數將參數2的值賦給參數1指向的值

  

  

   InterlockedExchangePointer

   參數爲PVOID* 類型,參數2爲PVOID類型。此函數功能同上。

  

  

   用InterlockedExchangeAdd來說明,他接受一個長整形變量的地址,然後將參數2的樹枝加到參數1制定的長整形數據上。我們前邊已經說了,他能保證當一個線程訪問此長整形變量時,其他線程無法訪問此變量,那麽他是如何實現的呢?答案取決于運行的是何種CPU平台。對于x86家族的CPU來說,互鎖函數會對總線發出一個硬件信號,防止另一個CPU訪問同一個內存地址。在Alpha平台上,互鎖函數能夠執行下列操作

  1) 打開C P U中的一個特殊的位標志,並注明被訪問的內存地址。

  2) 將內存的值讀入一個寄存器。

  3) 修改該寄存器。

  4) 如果C P U中的特殊位標志是關閉的,則轉入第二步。否則,特殊位標志仍然是打開的,寄存器的值重新存入內存。

   互鎖函數工作與用戶模式之下,所以他的速度是非常快點的。有利就有弊,互鎖函數最大的缺點莫過于使用範圍的狹隘性了,它更多的只是對單個變量的保護。

  2、臨界區

   也有的地方叫它關鍵代碼段。臨界區指一個小代碼段,在代碼能夠執行前,它必須獨占對某些共享資源的訪問權。這是讓若幹行代碼能夠“以原子操作方式”來使用資源的一種方法。所謂原子操作方式,是指該代碼知道沒有別的線程要訪問該資源。簡單的說,就是一次只能由一個線程來執行的一段代碼。

   先來看一段例子,在例子中,線程完成對一個數組初始化的工作,目標是在當前的數值上加1,TThread對象中還定義了一個FUseCritical的變量,它用來決定線程在執行時是否要使用臨界區的方式。

WIN32下DELPHI中的多線程【同步1】(四)
WIN32下DELPHI中的多線程【同步1】(四)
...{

WIN32下DELPHI中的多線程【同步1】(四)
作者:wudi_1982

WIN32下DELPHI中的多線程【同步1】(四)
聯系方式:wudi_1982@hotmail.com

WIN32下DELPHI中的多線程【同步1】(四)
本代碼爲演示代碼,只貼出了一些比較重要的代碼

WIN32下DELPHI中的多線程【同步1】(四)
轉載請著名出處

WIN32下DELPHI中的多線程【同步1】(四)
}

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
const

WIN32下DELPHI中的多線程【同步1】(四)
MaxArray = 1000;//公共內存區域的大小

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
//演示臨界區功能的線程類

WIN32下DELPHI中的多線程【同步1】(四)
type

WIN32下DELPHI中的多線程【同步1】(四)
TCriticalSectionThread= class(TThread)

WIN32下DELPHI中的多線程【同步1】(四)
private

WIN32下DELPHI中的多線程【同步1】(四)
FUseCritical : Boolean;//決定是否使用臨界區

WIN32下DELPHI中的多線程【同步1】(四)
procedure GetRestult;

WIN32下DELPHI中的多線程【同步1】(四)
protected

WIN32下DELPHI中的多線程【同步1】(四)
procedure Execute;override;

WIN32下DELPHI中的多線程【同步1】(四)
public

WIN32下DELPHI中的多線程【同步1】(四)
constructor Create(UseCritical : Boolean);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
....

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
var

WIN32下DELPHI中的多線程【同步1】(四)
PublicMem : array[0..MaxArray] of integer;//一塊公共區域

WIN32下DELPHI中的多線程【同步1】(四)
Cs : TRTLCriticalSection;//描述臨界區信息的數據結構

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
實現代碼如下:

WIN32下DELPHI中的多線程【同步1】(四)
WIN32下DELPHI中的多線程【同步1】(四)
...{ TCriticalSectionThread }

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
constructor TCriticalSectionThread.Create(UseCritical: Boolean);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//構造函數中接受是否使用臨界區的參數

WIN32下DELPHI中的多線程【同步1】(四)
FUseCritical := UseCritical;

WIN32下DELPHI中的多線程【同步1】(四)
inherited Create(false);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TCriticalSectionThread.Execute;

WIN32下DELPHI中的多線程【同步1】(四)
var

WIN32下DELPHI中的多線程【同步1】(四)
i : integer;

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
inherited;

WIN32下DELPHI中的多線程【同步1】(四)
//運行完畢後自動釋放資源

WIN32下DELPHI中的多線程【同步1】(四)
FreeOnTerminate := True;

WIN32下DELPHI中的多線程【同步1】(四)
//如果使用了臨界區,則進入臨界區

WIN32下DELPHI中的多線程【同步1】(四)
if FUseCritical then

WIN32下DELPHI中的多線程【同步1】(四)
EnterCriticalSection(cs);

WIN32下DELPHI中的多線程【同步1】(四)
//對數組初始化

WIN32下DELPHI中的多線程【同步1】(四)
for i := 0 to MaxArray do

WIN32下DELPHI中的多線程【同步1】(四)
inc(PublicMem[i]);

WIN32下DELPHI中的多線程【同步1】(四)
Synchronize(GetRestult);

WIN32下DELPHI中的多線程【同步1】(四)
//離開

WIN32下DELPHI中的多線程【同步1】(四)
if FUseCritical then

WIN32下DELPHI中的多線程【同步1】(四)
LeaveCriticalSection(Cs);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TCriticalSectionThread.GetRestult;

WIN32下DELPHI中的多線程【同步1】(四)
var

WIN32下DELPHI中的多線程【同步1】(四)
i : integer;

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//將結果顯示在Form1.listbox1中

WIN32下DELPHI中的多線程【同步1】(四)
for i := 0 to MaxArray do

WIN32下DELPHI中的多線程【同步1】(四)
Form1.ListBox1.Items.Add(inttostr(PublicMem[i]));

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
//調用這個線程類來演示臨界區功能的代碼

WIN32下DELPHI中的多線程【同步1】(四)
procedure TForm1.Button3Click(Sender: TObject);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//將公共內存區域填充爲0

WIN32下DELPHI中的多線程【同步1】(四)
FillMemory(@PublicMem,sizeof(PublicMem),0);

WIN32下DELPHI中的多線程【同步1】(四)
ListBox1.Clear;

WIN32下DELPHI中的多線程【同步1】(四)
//一個CheckBox,用來接受是否使用臨界區方式的信息

WIN32下DELPHI中的多線程【同步1】(四)
if ckbxUsesC.Checked then

WIN32下DELPHI中的多線程【同步1】(四)
//如果使用臨界區,則首先初始化

WIN32下DELPHI中的多線程【同步1】(四)
InitializeCriticalSection(cs);

WIN32下DELPHI中的多線程【同步1】(四)
//同時生成兩個線程

WIN32下DELPHI中的多線程【同步1】(四)
TCriticalSectionThread.Create(ckbxUsesC.Checked);

WIN32下DELPHI中的多線程【同步1】(四)
TCriticalSectionThread.Create(ckbxUsesC.Checked);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
//好的編碼習慣中,你應該在確定線程已經不再需要使用臨界區時,用DeleteCriticalSection(cs);清楚這個結構

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)


   整理上面代碼,並執行,在MaxArray定義比較大的時候(也就是一個線程完成工作需要時間比較長的時候),你會發現當不使用臨界區時,兩個進程“同時”出現對公共內存區的訪問,數組沒有按照你的預定方式進行初始化(理想的情況是數組先被初始化爲1,然後再是2,可實際情況,你可能看到在第一個線程對數組初始化時,第二個線程搶占了CPU,所以,大量的數組成員被改寫成了2),當使用臨界區時,你會發現數組按照我們設定的思路先被初始化爲1,然後再初始化爲2。

   讓我們來看看在使用臨界區的情況下系統是如何調度這兩個線程的,當第一個線程創建之後,它成爲可調度狀態,至于系統目前是否分配CPU時間片給它,我們不知道,這要看系統中其他進程的情況,然後第二個線程創建,並且也成爲可調度狀態,當系統發現可以調度這兩個線程的時候(也許在第一個線程創建之後,它就已經被調度了),系統調度一個線程,我們這裏暫且假設調度的是第一個線程,線程執行EnterCriticalSection(cs)更新CRITICAL_SECTION(DLEPHI中將它定義爲TRTLCriticalSection的記錄)的成員變量,以指明調用線程已被賦予訪問權並立即返回,使該線程能夠繼續運行,然後在一定時間之後,線程2搶占了CPU,然後執行EnterCriticalSection(cs),刷新CRITICAL_SECTION的成員變臉,系統發現一個線程已經被賦予了資源的訪問權,這時,系統將調用線程(我們這裏的線程2)置于等待狀態。這種情況是極好的,因爲等待的線程不會浪費任何CPU 時間。系統能夠記住該線程想要訪問該資源並且自動更新CRITICAL_SECTION的成員變量,直到線程1重新被調度,並執行了LeaveCriticalSection函數,這時系統便將線程2置爲可調度狀態,然後在合適的時間,線程2被調度,再次完成對數組初始化的工作。

  使用臨界區時要注意的內容

  1、EnterCriticalSection和LeaveCriticalSection要配對出現,如果你只調用EnterCriticalSection而忘記使用LeaveCriticalSection,那麽結果將是可怕的,這意味著其他需要訪問被保護資源的線程將永遠的等待下去,直到最終超時,産生一個異常條件。超時的時間被定義在注冊表的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager中,默認大約時30天的時間。

  2、CRITICAL_SECTION結構中的成員應該在任何線程試圖訪問被保護的資源之前初始化。你要調用InitializeCriticalSection來完成此操作。如果一個線程試圖進入未初始化的CRITICAL_SECTION,那麽結果將是無法預料的。

  3、當知道進程的線程不再試圖訪問共享資源時,用DeleteCriticalSection函數清楚CRITICAL_SECTION結構

  幾個有用的技巧

  1)、每個需保護的共享資源使用一個單獨的CRITICAL_SECTION變量,例如線程1和線程2訪問一個資源A,而線程1和線程3訪問另一個資源B,那最好都資源A、B都使用一個單獨的CRITICAL_SECTION變量,如果使用同一個CRITICAL_SECTION變量,那麽加入線程1先被調度了,線程2、3則只有等待線程1完成對A、B的使用後才有機會運行。如果使用單獨的CRITICAL_SECTION變量,則在線程1使用完A之後,線程2即可迅速成爲被調度狀態。

  2)、當要訪問多個被保護資源時,如果你使用的不同的CRITICAL_SECTION變量,那麽要注意他們的順序,例如線程1先後調用EnterCriticalSection(cs1);EnterCriticalSection(cs2),而有另外一個線程則使用另外的順序EnterCriticalSection(cs2),EnterCriticalSection(cs1),那麽將有可能出現死鎖的情況,線程1被調度,獲得被cs1保護的資源A的使用權,然後線程2被調度,獲得了被cs2保護的資源B的使用權,那麽此時,無論是線程1,還是線程2,都將因爲對方而一直等待下去。

  3)、不要在臨界區內長時間執行那些不需要使用保護資源的代碼。如果長時間執行那些不必要保護的代碼,其他的希望訪問保護資源的線程將長時間的等待下去。

  線程與內核對象的同步

   用戶方式同步的優點是它的同步速度非常快。雖然用戶方式的線程同步機制具有速度快的優點,但其局限性也是明顯的。例如,互鎖函數家族只能在單值上運行,根本無法使線程進入等待狀態。我們使用臨界區的方式可以使得線程進入等待狀態,但是只能用這些代碼段對單個進程中的線程實施同步。因爲在等待進臨界區時你無法方便的設定超時值,所以有可能出現死鎖的狀態。

   上面我一直強調了一個概念,就是等待狀態,這是很重要的,因爲等待狀態的線程將不使用CPU資源。

   內核對象機制的適應性遠遠優于用戶方式機制。實際上,內核對象機制的唯一不足之處是它的速度比較慢。《WINDOWS核心編程》一書中說”這個轉換需要很大的代價:往返一次需要占用x86平台上的大約1000個CPU周期,當然,這還不包括執行內核方式代碼,即實現線程調用的函數的代碼所需的時間。“,我沒有測試過,不知道這1000個CPU周期的說法是否准確,但可以肯定內核對象機制將比用戶模式下的同步要慢。

   Windows的內核對象,包括進程,線程和作業等。可以將所有這些內核對象用于同步目的。對于線程同步來說,這些內核對象中的每種對象都可以說是處于已通知或未通知的狀態之中。例如,進程內核對象總是在未通知狀態中創建的。當進程終止運行時,操作系統自動使該進程的內核對象處于已通知狀態。一旦進程內核對象得到通知,它將永遠保持這種狀態,它的狀態永遠不會改爲未通知狀態。當進程正在運行的時候,進程內核對象處于未通知狀態,當進程終止運行的時候,它就變爲已通知狀態。

   實際上,線程內核對象也遵循同樣的規則。與進程內核對象一樣,線程內核對象也可以處于已通知狀態或未通知狀態。

   下面的內核對象可以處于已通知狀態或未通知狀態:進程、文件修改通知線程、事件、作業、 可等待定時器、文件、 信標、控制台輸入、 互斥對象

   線程可以使自己進入等待狀態,直到一個對象變爲已通知狀態。注意,用于控制每個對象的已通知/未通知狀態的規則要根據對象的類型而定。

  等待函數

   最常用的莫過于WaitForSingleObject

   DWORD WaitForSingleObject(HANDLE hObject,DWORD dwMillseconds);

   當線程調用該函數時,第一個參數標識一個能夠支持被通知/未通知的內核對象。第二個參數允許該線程指明爲了等待該對象變爲已通知狀態,它將等待多長時間。WaitForSingleObject的返回值能夠指明調用線程爲什麽再次變爲可調度狀態。如果線程等待的對象變爲已通知狀態,那麽返回值是WAIT_OBJECT_0。如果設置的超時已經到期,則返回值是WAIT_TIMEOUT。如果將一個錯誤的值(如一個無效句柄)傳遞給WaitForSingleObject,那麽返回值將是WAIT_FAILED。

  事件對象

   在所有的內核對象中,事件內核對象是個最基本的對象。它們包含一個使用計數(與所有內核對象一樣),一個用于指明該事件是個自動重置的事件還是一個人工重置的事件的布爾值,另一個用于指明該事件處于已通知狀態還是未通知狀態的布爾值。

   事件能夠通知一個操作已經完成。有兩種不同類型的事件對象。一種是人工重置的事件,另一種是自動重置的事件。當人工重置的事件得到通知時,等待該事件的所有線程均變爲可調度線程。當一個自動重置的事件得到通知時,等待該事件的線程中只有一個線程變爲可調度線程。

   當一個線程執行初始化操作,然後通知另一個線程執行剩余的操作時,事件使用得最多。事件初始化爲未通知狀態,然後,當該線程完成它的初始化操作後,它就將事件設置爲已通知狀態。這時,一直在等待該事件的另一個線程發現該事件已經得到通知,因此它就變成可調度線程。這第二個線程知道第一個線程已經完成了它的操作。

   HANDLE CreateEvent(PSECURITY_ATTRIBUTS psa,

   bool fManualRest,

   bool fInitialState,

   PCTSTR pszname);

   第一個參數用來制定安全屬性,通常我們用null,最後一個參數用來制定一個名字。fManualRest,參數是個布爾值,它能夠告訴系統是創建一個人工重置的事件還是創建一個自動重置的事件(FALSE)。fInitialState,參數用于指明該事件是要初始化爲已通知狀態(TRUE)還是未通知狀態(FALSE)。當系統創建事件對象後,createEvent就將與進程相關的句柄返回給事件對象。其他進程中的線程可以獲得對該對象的訪問權,方法是使用在pszName參數中傳遞的相同值,使用繼承性,使用DuplicateHandle函數等來調用CreateEvent,或者調用OpenEvent,在pszName數中設定一個與調用CreateEvent時設定的名字相匹配的名字 。

   一旦事件已經創建,就可以直接控制它的狀態。當調用SetEvent時,可以將事件改爲已通知狀態:當調用ResetEvent函數時,可以將該事件改爲未通知狀態。

   自動重置的事件與人工重置事件的區別在于,自動重置事件在線程成功地等待到該對象時,自動重置的事件就會自動重置到未通知狀態。通常沒有必要爲自動重置的事件調用ResetEvent函數,因爲系統會自動對事件進行重置

  一個例子:

WIN32下DELPHI中的多線程【同步1】(四)
WIN32下DELPHI中的多線程【同步1】(四)
...{

WIN32下DELPHI中的多線程【同步1】(四)
作者:wudi_1982

WIN32下DELPHI中的多線程【同步1】(四)
聯系方式:wudi_1982@hotmail.com

WIN32下DELPHI中的多線程【同步1】(四)
本代碼只貼出了一些比較關鍵的部分

WIN32下DELPHI中的多線程【同步1】(四)
轉載請著名出處

WIN32下DELPHI中的多線程【同步1】(四)
}

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
//利用事件對象演示同步的TThread派生類

WIN32下DELPHI中的多線程【同步1】(四)
TEventThread=class(TThread)

WIN32下DELPHI中的多線程【同步1】(四)
private

WIN32下DELPHI中的多線程【同步1】(四)
CurCount : integer;//當前計數

WIN32下DELPHI中的多線程【同步1】(四)
Flabel : TLabel;//顯示當前計數的Tlabel組建

WIN32下DELPHI中的多線程【同步1】(四)
procedure GetRestult;

WIN32下DELPHI中的多線程【同步1】(四)
protected

WIN32下DELPHI中的多線程【同步1】(四)
procedure Execute;override;

WIN32下DELPHI中的多線程【同步1】(四)
public

WIN32下DELPHI中的多線程【同步1】(四)
constructor Create(Alabel : TLabel);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
var

WIN32下DELPHI中的多線程【同步1】(四)
EventHandle : THandle;//事件對象的句柄

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
//TEventThread的實現代碼

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
WIN32下DELPHI中的多線程【同步1】(四)
...{ TEventThread }

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
constructor TEventThread.Create(Alabel: TLabel);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
Flabel := Alabel;

WIN32下DELPHI中的多線程【同步1】(四)
inherited Create(False);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TEventThread.Execute;

WIN32下DELPHI中的多線程【同步1】(四)
var

WIN32下DELPHI中的多線程【同步1】(四)
i : integer;

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
inherited;

WIN32下DELPHI中的多線程【同步1】(四)
CurCount := 0;

WIN32下DELPHI中的多線程【同步1】(四)
for i := 0 to 10000 do

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
case WaitForSingleObject(EventHandle,5000) of

WIN32下DELPHI中的多線程【同步1】(四)
WAIT_OBJECT_0 : begin//如果等待到事件對象,則將當前技術加1,並且顯示在指定label上

WIN32下DELPHI中的多線程【同步1】(四)
Inc(CurCount);

WIN32下DELPHI中的多線程【同步1】(四)
Synchronize(GetRestult);

WIN32下DELPHI中的多線程【同步1】(四)
Sleep(0);

WIN32下DELPHI中的多線程【同步1】(四)
//關于sleep,switchtoThread的使用前面已經說了

WIN32下DELPHI中的多線程【同步1】(四)
// SwitchToThread

WIN32下DELPHI中的多線程【同步1】(四)
//Application.ProcessMessages;

WIN32下DELPHI中的多線程【同步1】(四)
end;//WAIT_OBJECT_0

WIN32下DELPHI中的多線程【同步1】(四)
WAIT_TIMEOUT : begin//超時則自動重置當前計數

WIN32下DELPHI中的多線程【同步1】(四)
CurCount := 0;

WIN32下DELPHI中的多線程【同步1】(四)
Synchronize(GetRestult);

WIN32下DELPHI中的多線程【同步1】(四)
SwitchToThread;

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TEventThread.GetRestult;

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
Flabel.Caption := IntToStr(CurCount);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
//窗體單元中測試TEventThread的一些代碼

WIN32下DELPHI中的多線程【同步1】(四)
procedure TForm1.CreateTClick(Sender: TObject);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//這裏創建了TEventThread線程類的兩個實例,目的是更好的演示自動重置和手動重置的區別

WIN32下DELPHI中的多線程【同步1】(四)
TEventThread.Create(labEvent);

WIN32下DELPHI中的多線程【同步1】(四)
TEventThread.Create(labEvent2);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TForm1.CreateEClick(Sender: TObject);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//生成一個事件對象,事件對象的重置方式以及初始化狀態通過兩個checkBox來決定

WIN32下DELPHI中的多線程【同步1】(四)
EventHandle := CreateEvent(nil,ckbxAutoReset.Checked, ckbxInitEventState.Checked,pchar('MyEvent'));

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TForm1.SetEClick(Sender: TObject);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//通知

WIN32下DELPHI中的多線程【同步1】(四)
SetEvent(EventHandle);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TForm1.ResetEClick(Sender: TObject);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//未通知

WIN32下DELPHI中的多線程【同步1】(四)
ResetEvent(EventHandle);

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)
procedure TForm1.closeClick(Sender: TObject);

WIN32下DELPHI中的多線程【同步1】(四)
begin

WIN32下DELPHI中的多線程【同步1】(四)
//再你確定不需要此事件對象的時候,記得釋放資源

WIN32下DELPHI中的多線程【同步1】(四)
CloseHandle(EventHandle)

WIN32下DELPHI中的多線程【同步1】(四)
end;

WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)


WIN32下DELPHI中的多線程【同步1】(四)


  利用事件對象演示同步的程序界面

WIN32下DELPHI中的多線程【同步1】(四)


   整理上述代碼,然後分別用不同的配置不同順序的點擊按鈕,可以讓你對事件對象的使用加深了解。

   內核方式的同步還有很多種,但原理基本都一樣,後續文章對盡可能的依次舉例列舉。

  參考文獻:《WINDOWS核心編程》

   注:轉載請著名出處,謝謝
 
 
 
上一篇《WIN32下DELPHI中的多線程【深入VCL源碼】(一)》
下一篇《WIN32下DELPHI中的多線程【同步2】(五)》
 
 
 
 
 
 
日版寵物情人插曲《Winding Road》歌詞

日版寵物情人2017的插曲,很帶節奏感,日語的,女生唱的。 最後聽見是在第8集的時候女主手割傷了,然後男主用嘴幫她吸了一下,插曲就出來了。 歌手:Def...

兄弟共妻,我成了他們夜裏的美食

老鍾家的兩個兒子很特別,就是跟其他的人不太一樣,魔一般的執著。兄弟倆都到了要結婚的年齡了,不管自家老爹怎麽磨破嘴皮子,兄弟倆說不娶就不娶,老父母爲兄弟兩操碎了心...

如何磨出破洞牛仔褲?牛仔褲怎麽剪破洞?

把牛仔褲磨出有線的破洞 1、具體工具就是磨腳石,下面墊一個硬物,然後用磨腳石一直磨一直磨,到把那塊磨薄了,用手撕開就好了。出來的洞啊很自然的。需要貓須的話調幾...

我就是掃描下圖得到了敬業福和愛國福

先來看下敬業福和愛國福 今年春節,支付寶再次推出了“五福紅包”活動,表示要“把欠大家的敬業福都還給大家”。 今天該活動正式啓動,和去年一樣,需要收集“五福”...

冰箱異味産生的原因和臭味去除的方法

有時候我們打開冰箱就會聞到一股異味,冰箱裏的這種異味是因爲一些物質發出的氣味的混合體,聞起來讓人惡心。 産生這些異味的主要原因有以下幾點。 1、很多人有這種習...

《極品家丁》1-31集大結局分集劇情介紹

簡介 《極品家丁》講述了現代白領林晚榮無意回到古代金陵,並追隨蕭二小姐化名“林三”進入蕭府,不料卻陰差陽錯上演了一出低級家丁拼搏上位的“林三升職記”。...

李溪芮《極品家丁》片尾曲《你就是我最愛的寶寶》歌詞

你就是我最愛的寶寶 - 李溪芮 (電視劇《極品家丁》片尾曲) 作詞:常馨內 作曲:常馨內 你的眉 又鬼馬的挑 你的嘴 又壞壞的笑 上一秒吵鬧 下...

烏梅的功效與作用以及烏梅的食用禁忌有哪些?

烏梅,又稱春梅,中醫認爲,烏梅味酸,性溫,無毒,具有安心、除熱、下氣、祛痰、止渴調中、殺蟲的功效,治肢體痛、肺痨病。烏梅泡水喝能治傷寒煩熱、止吐瀉,與幹姜一起制...

什麽是脂肪粒?如何消除臉部脂肪粒?

什麽是脂肪粒 在我們的臉上總會長一個個像脂肪的小顆粒,弄也弄不掉,而且顔色還是白白的。它既不是粉刺也不是其他的任何痘痘,它就是脂肪粒。 脂肪粒雖然也是由油脂...

網絡安全治理:國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰受害者

來源:中國青年報 新的攻擊方法不斷湧現,黑客幾乎永遠占據網絡攻擊的上風,我們不可能通過技術手段杜絕網絡攻擊。國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰...

河南夫妻在溫嶺網絡直播“造人”內容涉黃被刑事拘留

夫妻網絡直播“造人”爆紅   1月9日,溫嶺城北派出所接到南京警方的協查通告,他們近期打掉了一個涉黃直播APP平台。而根據掌握的線索,其中有一對涉案的夫妻主播...

如何防止牆紙老化?牆紙變舊變黃怎麽辦?

如何防止牆紙老化? (1)選擇透氣性好的牆紙 市場上牆紙的材質分無紡布的、木纖維的、PVC的、玻璃纖維基材的、布面的等,相對而言,PVC材質的牆紙最不透氣...

鮮肌之謎非日本生産VS鮮肌之謎假日貨是謠言

觀點一:破日本銷售量的“鮮肌之謎” 非日本生産 近一段時間,淘寶上架了一款名爲“鮮肌之謎的” 鲑魚卵巢美容液,號稱是最近日本的一款推出的全新護膚品,産品本身所...

中國最美古詩詞精選摘抄

系腰裙(北宋詞人 張先) 惜霜蟾照夜雲天,朦胧影、畫勾闌。人情縱似長情月,算一年年。又能得、幾番圓。 欲寄西江題葉字,流不到、五亭前。東池始有荷新綠,尚小如...

關于女人的經典語句

關于女人的經典語句1、【做一個獨立的女人】 思想獨立:有主見、有自己的人生觀、價值觀。有上進心,永遠不放棄自己的理想,做一份自己喜愛的事業,擁有快樂和成就...

未來我們可以和性愛機器人結婚嗎?

你想體驗機器人性愛嗎?你想和性愛機器人結婚嗎?如果你想,機器人有拒絕你的權利嗎? 近日,第二屆“國際人類-機器人性愛研討會”大會在倫敦金史密斯大學落下帷幕。而...

全球最變態的十個地方

10.土耳其地下洞穴城市 變態指數:★★☆☆☆ 這是土耳其卡帕多西亞的一個著名景點,傳說是當年基督教徒們爲了躲避戰爭而在此修建。裏面曾住著20000人,...

科學家稱,人類死亡後意識將在另外一個宇宙中繼續存活

據英國《每日快報》報道,一位科學家兼理論家Robert Lanza博士宣稱,世界上並不存在人類死亡,死亡的只是身體。他認爲我們的意識借助我們體內的能量生存,而且...

《屏裏狐》片頭曲《我愛狐狸精》歌詞是什麽?

《我愛狐狸精》 - 劉馨棋   (電視劇《屏裏狐》主題曲)   作詞:金十三&李旦   作曲:劉嘉   狐狸精 狐狸仙   千年修...

 
 
 
線程的同步 在使用的時候,多線程最讓人頭疼的也許就是同步了。 如果你的線程只是完成一件並不需要訪問線程對象外部資源的工作,在這種情況下,線程互相之間不需要進行通信,此時Windows的運行性能最好。但是,線程很少能夠在所有的時間都獨立地進行操作。通常情況下,要生成一些線程來處理某個任務。當這個任務完成時,另一個線程必須了解這個情況。 系統中的所有線程都必須擁有對各種系統資源的訪問權,這些資源包括內存堆棧,文件,窗口和許多其他資源。如果一個線程需要獨占對資源的訪問權,那麽其他線程就無法完成它們的工作。反過來說,也不能讓任何一個線程在任何時間都能訪問所有的資源。如果在一個線程從內存塊中讀取數據時,另一個線程卻想要將數據寫入同一個內存塊,那麽這就像你在讀一本書時另一個人卻在修改書中的內容一樣。這樣,書中的內容就會被搞得亂七八糟,結果什麽也看不清楚。 線程需要在下面兩種情況下互相進行通信: • 當有多個線程訪問共享資源而不使資源被破壞時。 • 當一個線程需要將某個任務已經完成的情況通知另外一個或多個線程時。 線程的同步包括許多方面的內容,Windows提供了許多方法,可以非常容易地實現線程的同步。但是,要想隨時了解一連串的線程想要做什麽,那是非常困難的。我們的頭腦的工作不是異步的,我們希望以一種有序的方式來思考許多事情,每次前進一步。不過多線程環境不是這樣運行的。你幾乎無法完全知道目標系統中存在多少線程,也不知道他們處在什麽狀態下,更不知道他們要幹什麽。 用戶方式下的線程同步 1、互鎖函數   在MSDN關于同步函數的幫助文檔中,你會看到大量的互鎖函數。他們大多以Interlocked****的名字存在。互鎖函數運行在用戶模式。它能保證當一個線程訪問一個變量時,其它線程無法訪問此變量,以確保變量值的唯一性。這種訪問方式被稱爲原子訪問。 常用的互鎖函數及其功能見如下列表: 函數 參數和功能 InterlockedIncrement 參數爲PLONG類型。此函數使一個LONG變量增1 InterlockedDecrement 參數爲PLONG類型。此函數使一個LONG變量減1 InterlockedExchangeAdd 參數1爲PLONG類型,參數2爲LONG類型。此函數將參數2賦給參數1指向的值 InterlockedExchange 參數1爲PLONG類型,參數2爲LONG類型。此函數將參數2的值賦給參數1指向的值 InterlockedExchangePointer 參數爲PVOID* 類型,參數2爲PVOID類型。此函數功能同上。   用InterlockedExchangeAdd來說明,他接受一個長整形變量的地址,然後將參數2的樹枝加到參數1制定的長整形數據上。我們前邊已經說了,他能保證當一個線程訪問此長整形變量時,其他線程無法訪問此變量,那麽他是如何實現的呢?答案取決于運行的是何種CPU平台。對于x86家族的CPU來說,互鎖函數會對總線發出一個硬件信號,防止另一個CPU訪問同一個內存地址。在Alpha平台上,互鎖函數能夠執行下列操作 1) 打開C P U中的一個特殊的位標志,並注明被訪問的內存地址。 2) 將內存的值讀入一個寄存器。 3) 修改該寄存器。 4) 如果C P U中的特殊位標志是關閉的,則轉入第二步。否則,特殊位標志仍然是打開的,寄存器的值重新存入內存。 互鎖函數工作與用戶模式之下,所以他的速度是非常快點的。有利就有弊,互鎖函數最大的缺點莫過于使用範圍的狹隘性了,它更多的只是對單個變量的保護。 2、臨界區 也有的地方叫它關鍵代碼段。臨界區指一個小代碼段,在代碼能夠執行前,它必須獨占對某些共享資源的訪問權。這是讓若幹行代碼能夠“以原子操作方式”來使用資源的一種方法。所謂原子操作方式,是指該代碼知道沒有別的線程要訪問該資源。簡單的說,就是一次只能由一個線程來執行的一段代碼。 先來看一段例子,在例子中,線程完成對一個數組初始化的工作,目標是在當前的數值上加1,TThread對象中還定義了一個FUseCritical的變量,它用來決定線程在執行時是否要使用臨界區的方式。 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][/url][url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][/url]...{ [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 作者:wudi_1982 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 聯系方式:wudi_1982@hotmail.com [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 本代碼爲演示代碼,只貼出了一些比較重要的代碼 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 轉載請著名出處 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif[/img][/url]} [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]const [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] MaxArray = 1000;//公共內存區域的大小 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//演示臨界區功能的線程類 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]type [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TCriticalSectionThread= class(TThread) [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] private [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] FUseCritical : Boolean;//決定是否使用臨界區 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] procedure GetRestult; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] protected [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] procedure Execute;override; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] public [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] constructor Create(UseCritical : Boolean); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url].... [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]var [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] PublicMem : array[0..MaxArray] of integer;//一塊公共區域 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Cs : TRTLCriticalSection;//描述臨界區信息的數據結構 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]實現代碼如下: [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][/url][url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][/url]...{ TCriticalSectionThread } [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]constructor TCriticalSectionThread.Create(UseCritical: Boolean); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //構造函數中接受是否使用臨界區的參數 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] FUseCritical := UseCritical; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inherited Create(false); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TCriticalSectionThread.Execute; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]var [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] i : integer; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inherited; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //運行完畢後自動釋放資源 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] FreeOnTerminate := True; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //如果使用了臨界區,則進入臨界區 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] if FUseCritical then [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] EnterCriticalSection(cs); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //對數組初始化 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] for i := 0 to MaxArray do [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inc(PublicMem[i]); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Synchronize(GetRestult); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //離開 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] if FUseCritical then [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] LeaveCriticalSection(Cs); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TCriticalSectionThread.GetRestult; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]var [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] i : integer; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //將結果顯示在Form1.listbox1中 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] for i := 0 to MaxArray do [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Form1.ListBox1.Items.Add(inttostr(PublicMem[i])); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//調用這個線程類來演示臨界區功能的代碼 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.Button3Click(Sender: TObject); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //將公共內存區域填充爲0 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] FillMemory(@PublicMem,sizeof(PublicMem),0); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] ListBox1.Clear; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //一個CheckBox,用來接受是否使用臨界區方式的信息 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] if ckbxUsesC.Checked then [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //如果使用臨界區,則首先初始化 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] InitializeCriticalSection(cs); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //同時生成兩個線程 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TCriticalSectionThread.Create(ckbxUsesC.Checked); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TCriticalSectionThread.Create(ckbxUsesC.Checked); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//好的編碼習慣中,你應該在確定線程已經不再需要使用臨界區時,用DeleteCriticalSection(cs);清楚這個結構 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] 整理上面代碼,並執行,在MaxArray定義比較大的時候(也就是一個線程完成工作需要時間比較長的時候),你會發現當不使用臨界區時,兩個進程“同時”出現對公共內存區的訪問,數組沒有按照你的預定方式進行初始化(理想的情況是數組先被初始化爲1,然後再是2,可實際情況,你可能看到在第一個線程對數組初始化時,第二個線程搶占了CPU,所以,大量的數組成員被改寫成了2),當使用臨界區時,你會發現數組按照我們設定的思路先被初始化爲1,然後再初始化爲2。 讓我們來看看在使用臨界區的情況下系統是如何調度這兩個線程的,當第一個線程創建之後,它成爲可調度狀態,至于系統目前是否分配CPU時間片給它,我們不知道,這要看系統中其他進程的情況,然後第二個線程創建,並且也成爲可調度狀態,當系統發現可以調度這兩個線程的時候(也許在第一個線程創建之後,它就已經被調度了),系統調度一個線程,我們這裏暫且假設調度的是第一個線程,線程執行EnterCriticalSection(cs)更新CRITICAL_SECTION(DLEPHI中將它定義爲TRTLCriticalSection的記錄)的成員變量,以指明調用線程已被賦予訪問權並立即返回,使該線程能夠繼續運行,然後在一定時間之後,線程2搶占了CPU,然後執行EnterCriticalSection(cs),刷新CRITICAL_SECTION的成員變臉,系統發現一個線程已經被賦予了資源的訪問權,這時,系統將調用線程(我們這裏的線程2)置于等待狀態。這種情況是極好的,因爲等待的線程不會浪費任何CPU 時間。系統能夠記住該線程想要訪問該資源並且自動更新CRITICAL_SECTION的成員變量,直到線程1重新被調度,並執行了LeaveCriticalSection函數,這時系統便將線程2置爲可調度狀態,然後在合適的時間,線程2被調度,再次完成對數組初始化的工作。 使用臨界區時要注意的內容 1、EnterCriticalSection和LeaveCriticalSection要配對出現,如果你只調用EnterCriticalSection而忘記使用LeaveCriticalSection,那麽結果將是可怕的,這意味著其他需要訪問被保護資源的線程將永遠的等待下去,直到最終超時,産生一個異常條件。超時的時間被定義在注冊表的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager中,默認大約時30天的時間。 2、CRITICAL_SECTION結構中的成員應該在任何線程試圖訪問被保護的資源之前初始化。你要調用InitializeCriticalSection來完成此操作。如果一個線程試圖進入未初始化的CRITICAL_SECTION,那麽結果將是無法預料的。 3、當知道進程的線程不再試圖訪問共享資源時,用DeleteCriticalSection函數清楚CRITICAL_SECTION結構 幾個有用的技巧 1)、每個需保護的共享資源使用一個單獨的CRITICAL_SECTION變量,例如線程1和線程2訪問一個資源A,而線程1和線程3訪問另一個資源B,那最好都資源A、B都使用一個單獨的CRITICAL_SECTION變量,如果使用同一個CRITICAL_SECTION變量,那麽加入線程1先被調度了,線程2、3則只有等待線程1完成對A、B的使用後才有機會運行。如果使用單獨的CRITICAL_SECTION變量,則在線程1使用完A之後,線程2即可迅速成爲被調度狀態。 2)、當要訪問多個被保護資源時,如果你使用的不同的CRITICAL_SECTION變量,那麽要注意他們的順序,例如線程1先後調用EnterCriticalSection(cs1);EnterCriticalSection(cs2),而有另外一個線程則使用另外的順序EnterCriticalSection(cs2),EnterCriticalSection(cs1),那麽將有可能出現死鎖的情況,線程1被調度,獲得被cs1保護的資源A的使用權,然後線程2被調度,獲得了被cs2保護的資源B的使用權,那麽此時,無論是線程1,還是線程2,都將因爲對方而一直等待下去。 3)、不要在臨界區內長時間執行那些不需要使用保護資源的代碼。如果長時間執行那些不必要保護的代碼,其他的希望訪問保護資源的線程將長時間的等待下去。 線程與內核對象的同步 用戶方式同步的優點是它的同步速度非常快。雖然用戶方式的線程同步機制具有速度快的優點,但其局限性也是明顯的。例如,互鎖函數家族只能在單值上運行,根本無法使線程進入等待狀態。我們使用臨界區的方式可以使得線程進入等待狀態,但是只能用這些代碼段對單個進程中的線程實施同步。因爲在等待進臨界區時你無法方便的設定超時值,所以有可能出現死鎖的狀態。 上面我一直強調了一個概念,就是等待狀態,這是很重要的,因爲等待狀態的線程將不使用CPU資源。 內核對象機制的適應性遠遠優于用戶方式機制。實際上,內核對象機制的唯一不足之處是它的速度比較慢。《WINDOWS核心編程》一書中說”這個轉換需要很大的代價:往返一次需要占用x86平台上的大約1000個CPU周期,當然,這還不包括執行內核方式代碼,即實現線程調用的函數的代碼所需的時間。“,我沒有測試過,不知道這1000個CPU周期的說法是否准確,但可以肯定內核對象機制將比用戶模式下的同步要慢。 Windows的內核對象,包括進程,線程和作業等。可以將所有這些內核對象用于同步目的。對于線程同步來說,這些內核對象中的每種對象都可以說是處于已通知或未通知的狀態之中。例如,進程內核對象總是在未通知狀態中創建的。當進程終止運行時,操作系統自動使該進程的內核對象處于已通知狀態。一旦進程內核對象得到通知,它將永遠保持這種狀態,它的狀態永遠不會改爲未通知狀態。當進程正在運行的時候,進程內核對象處于未通知狀態,當進程終止運行的時候,它就變爲已通知狀態。 實際上,線程內核對象也遵循同樣的規則。與進程內核對象一樣,線程內核對象也可以處于已通知狀態或未通知狀態。 下面的內核對象可以處于已通知狀態或未通知狀態:進程、文件修改通知線程、事件、作業、 可等待定時器、文件、 信標、控制台輸入、 互斥對象 線程可以使自己進入等待狀態,直到一個對象變爲已通知狀態。注意,用于控制每個對象的已通知/未通知狀態的規則要根據對象的類型而定。 等待函數 最常用的莫過于WaitForSingleObject DWORD WaitForSingleObject(HANDLE hObject,DWORD dwMillseconds); 當線程調用該函數時,第一個參數標識一個能夠支持被通知/未通知的內核對象。第二個參數允許該線程指明爲了等待該對象變爲已通知狀態,它將等待多長時間。WaitForSingleObject的返回值能夠指明調用線程爲什麽再次變爲可調度狀態。如果線程等待的對象變爲已通知狀態,那麽返回值是WAIT_OBJECT_0。如果設置的超時已經到期,則返回值是WAIT_TIMEOUT。如果將一個錯誤的值(如一個無效句柄)傳遞給WaitForSingleObject,那麽返回值將是WAIT_FAILED。 事件對象 在所有的內核對象中,事件內核對象是個最基本的對象。它們包含一個使用計數(與所有內核對象一樣),一個用于指明該事件是個自動重置的事件還是一個人工重置的事件的布爾值,另一個用于指明該事件處于已通知狀態還是未通知狀態的布爾值。 事件能夠通知一個操作已經完成。有兩種不同類型的事件對象。一種是人工重置的事件,另一種是自動重置的事件。當人工重置的事件得到通知時,等待該事件的所有線程均變爲可調度線程。當一個自動重置的事件得到通知時,等待該事件的線程中只有一個線程變爲可調度線程。 當一個線程執行初始化操作,然後通知另一個線程執行剩余的操作時,事件使用得最多。事件初始化爲未通知狀態,然後,當該線程完成它的初始化操作後,它就將事件設置爲已通知狀態。這時,一直在等待該事件的另一個線程發現該事件已經得到通知,因此它就變成可調度線程。這第二個線程知道第一個線程已經完成了它的操作。 HANDLE CreateEvent(PSECURITY_ATTRIBUTS psa, bool fManualRest, bool fInitialState, PCTSTR pszname); 第一個參數用來制定安全屬性,通常我們用null,最後一個參數用來制定一個名字。fManualRest,參數是個布爾值,它能夠告訴系統是創建一個人工重置的事件還是創建一個自動重置的事件(FALSE)。fInitialState,參數用于指明該事件是要初始化爲已通知狀態(TRUE)還是未通知狀態(FALSE)。當系統創建事件對象後,createEvent就將與進程相關的句柄返回給事件對象。其他進程中的線程可以獲得對該對象的訪問權,方法是使用在pszName參數中傳遞的相同值,使用繼承性,使用DuplicateHandle函數等來調用CreateEvent,或者調用OpenEvent,在pszName數中設定一個與調用CreateEvent時設定的名字相匹配的名字 。 一旦事件已經創建,就可以直接控制它的狀態。當調用SetEvent時,可以將事件改爲已通知狀態:當調用ResetEvent函數時,可以將該事件改爲未通知狀態。 自動重置的事件與人工重置事件的區別在于,自動重置事件在線程成功地等待到該對象時,自動重置的事件就會自動重置到未通知狀態。通常沒有必要爲自動重置的事件調用ResetEvent函數,因爲系統會自動對事件進行重置 一個例子: [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][/url][url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][/url]...{ [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 作者:wudi_1982 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 聯系方式:wudi_1982@hotmail.com [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 本代碼只貼出了一些比較關鍵的部分 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 轉載請著名出處 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif[/img][/url]} [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//利用事件對象演示同步的TThread派生類 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TEventThread=class(TThread) [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] private [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CurCount : integer;//當前計數 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Flabel : TLabel;//顯示當前計數的Tlabel組建 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] procedure GetRestult; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] protected [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] procedure Execute;override; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] public [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] constructor Create(Alabel : TLabel); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]var [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] EventHandle : THandle;//事件對象的句柄 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//TEventThread的實現代碼 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][/url][url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][/url]...{ TEventThread } [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]constructor TEventThread.Create(Alabel: TLabel); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Flabel := Alabel; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inherited Create(False); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TEventThread.Execute; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]var [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] i : integer; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inherited; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CurCount := 0; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] for i := 0 to 10000 do [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] case WaitForSingleObject(EventHandle,5000) of [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] WAIT_OBJECT_0 : begin//如果等待到事件對象,則將當前技術加1,並且顯示在指定label上 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Inc(CurCount); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Synchronize(GetRestult); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Sleep(0); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //關于sleep,switchtoThread的使用前面已經說了 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] // SwitchToThread [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //Application.ProcessMessages; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end;//WAIT_OBJECT_0 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] WAIT_TIMEOUT : begin//超時則自動重置當前計數 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CurCount := 0; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Synchronize(GetRestult); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SwitchToThread; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TEventThread.GetRestult; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Flabel.Caption := IntToStr(CurCount); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//窗體單元中測試TEventThread的一些代碼 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.CreateTClick(Sender: TObject); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //這裏創建了TEventThread線程類的兩個實例,目的是更好的演示自動重置和手動重置的區別 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TEventThread.Create(labEvent); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TEventThread.Create(labEvent2); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.CreateEClick(Sender: TObject); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //生成一個事件對象,事件對象的重置方式以及初始化狀態通過兩個checkBox來決定 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] EventHandle := CreateEvent(nil,ckbxAutoReset.Checked, ckbxInitEventState.Checked,pchar('MyEvent')); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.SetEClick(Sender: TObject); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //通知 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SetEvent(EventHandle); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.ResetEClick(Sender: TObject); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //未通知 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] ResetEvent(EventHandle); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.closeClick(Sender: TObject); [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //再你確定不需要此事件對象的時候,記得釋放資源 [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CloseHandle(EventHandle) [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end; [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] [url=/bbs/detail_566602.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] 利用事件對象演示同步的程序界面 [url=/bbs/detail_566602.html][img]http://p.blog.csdn.net/images/p_blog_csdn_net/wudi_1982/利用事件對象演示線程同步的界面.JPG[/img][/url] 整理上述代碼,然後分別用不同的配置不同順序的點擊按鈕,可以讓你對事件對象的使用加深了解。 內核方式的同步還有很多種,但原理基本都一樣,後續文章對盡可能的依次舉例列舉。 參考文獻:《WINDOWS核心編程》 注:轉載請著名出處,謝謝
󰈣󰈤
 
 
 
  免責聲明:本文僅代表作者個人觀點,與王朝網路無關。王朝網路登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
 
陽光靓麗的模特兒(8)
陽光靓麗的模特兒(7)
陽光靓麗的模特兒(6)
陽光靓麗的模特兒(5)
秋-印象
德慶盤龍峽 一
松江印象之三
雲之南(寬幅)
 
>>返回首頁<<
 
 
 
 熱帖排行
 
 
 
 
© 2005- 王朝網路 版權所有