Wednesday, March 25, 2009

MFC 多執行緒的鎖 - Lock

設計多執緒程式可以避免主程式執行工作時,被運算量較大的工作給絆住,造成視窗延遲的現象。但是在這樣的情況下,主程式的使用者可能會重複觸發程式中的子執行緒行程,使得同時有2個以上的相同子執行緒在工作。此外例如子執行緒工作尚未結束前,主程式的某某些特定工作時必須要等待子執緒的工作完成,程式該如何撰寫。類似的問題,可透過 Lock 來完成。

MFC 的 Lock 主要是由以下這幾項構成︰
CSemaphore mutex; // 全域變數,用來計數 lock 數
CSingleLock wait(&mutex); // 操作 lock 的類別
wait.Lock(INFINITE); // 要求鎖定 mutex
wait.Unlock(); // 要求解鎖 mutex

當程式嘗試呼叫 wait.Lock(INFINITE); 鎖定 mutex 時,若 mutex 已經在其他地方被鎖定,則程式在此處會停擺,直到其他地方解除鎖定。


#include "testview.h"
#include <>

CSemaphore mutex; // 宣告

UINT ChildThread_Function ( LPVOID param )
{
 CSingleLock wait(&mutex); // 操作 mutex 的類別
 wait.Lock(INFINITE); // 要求鎖定 mutex

 CTestView* view = (CTestView*) param;
 param->DoSomething();

 wait.Unlock(); // 要求解鎖 mutex
}

CTestView::DoSomething()
{
 ....
}

CTestView::Execute()
{
 AfxBeginThread( ChildThread_Function, (LPVOID) this, THREAD_PRIORITY_ABOVE_NORMAL); // 呼叫子執行緒
}

*************************************************************************************

若目的只要要求同一個 ChildTread 同一時間只能有一個執行,則可以使用較簡單的 Critical Section 方法。

CRITICAL_SECTION csObject; // 宣告為全域
InitialCriticalSection(&csObject); // 在主程式中初始化
EnterCriticalSection(&csObject); // 在ChildThread的開頭呼叫
LeaveCriticalSection(&csObject); // 在 ChildThread的結尾呼叫

#include "testview.h"
#include <>

CRITICAL_SECTION csObject; // 宣告

UINT ChildThread_Function ( LPVOID param )
{
 EnterCriticalSection(&csObject); // 鎖定

 CTestView* view = (CTestView*) param;
 param->DoSomething();

 LeaveCriticalSection(&csObject); // 解鎖
}

CTestView::CTestView()
{
 InitialCriticalSection(&csObject); // 初始化
}

CTestView::DoSomething()
{
 ....
}

CTestView::Execute()
{
 AfxBeginThread( ChildThread_Function, (LPVOID) this, THREAD_PRIORITY_ABOVE_NORMAL); // 呼叫子執行緒
}

No comments: