執行緒通訊初探 (轉)
執行緒通訊初探 (轉)[@more@] 程式是執行中的,有獨立的,控制程式碼和其它的資源,一個獨立的程式可以包含多條路徑,即執行緒。一個可以被多個執行緒訪問,多個執行緒可以訪問同一個全域性變數。
提供兩種執行緒,介面執行緒和輔助執行緒。使用者介面執行緒有視窗,因此有自己的訊息迴圈,輔助執行緒沒有視窗,不需要處理訊息。但是輔助執行緒非常有用而且很容易,比如程式在某個執行時間要完成多個(很笨重的)任務時,顯然,輔助執行緒的使用會使程式的執行大大的提高。但是,執行緒間的通訊是一個必須解決的問題。
下面我們就來討論一下執行緒間的通訊的問題:
一.執行緒的管理
1.執行緒的啟動:
在使用輔助執行緒時,我們必須為執行緒寫一個全域性函式,它的返回值必須為 UINT型別,而且必須有LPVOID型別的引數,啟動執行緒下面的函式:
CWinThread* pThread=AfxBeginThread(
AFX_THREADPPOC ThreadProc,
LPVOID pParam,
int nPriority,
UINT nStackSize,
D dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs);
全域性函式必須定義為 UINT ThreadProc(LPVOID pParam);
AfxBeginThread會立即返回一個指向新建立的執行緒的指標,用來管理線 程,包括掛起和恢復執行緒的執行,但是執行緒物件沒有成員函式來中止執行緒的運 行。AfxBeginThread的第二個引數是一個32位的值,用來傳給全域性函式;第三 個引數用來設定執行緒的優先順序;而第四和第六個引數用來指定執行緒堆疊大小和 性,一般採用預設值0;第五個引數用來設定建立執行緒物件的方式,0為立 即執行,CREATE_SUSPEND為執行緒透過ResumeThread後才執行。
而執行緒優先順序的設定和獲得可以透過下面的兩個函式來實現:
pThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NOMAL);和
int nPriority=pThread->GetThreadPriority();
2.執行緒的中止:
可以呼叫MFC的AfxEndThread函式;
3.檢查執行緒是否結束:
呼叫函式GetExitCodeThread,
DWORD ExitCode ;
::GetExitCodeThread(pThread->m_hThread,&ExitCode );
if(ExitCode==STILL_ACTIVE)
//執行中
else //執行緒已經中止
二.主執行緒和輔助執行緒的通訊
主執行緒和輔助執行緒間的通訊方式有很多種,最簡單的就是利用全域性變數。 這裡利用訊息通訊是行不通的,因為輔助執行緒沒有訊息迴圈,不能夠利用 Windows訊息。
下面我們用一個例子來說明。在例子中,我們寫一個非常笨的函式,如實 現500*3000*3000的加法資料處理函式Add(int nCount);
我們在對話方塊上放置Start、Cancel按鈕和一個用來表示資料處理進度的進度條 。
1.利用全域性變數來實現主執行緒和輔助執行緒的通訊:
我們編寫全域性函式如下:
UINT ThreadProc(LPVOID pParam)
{
nCount=0;//全域性變數
while(nCount<500)
{
Add(nCount);
::InterlockedIncrement((long*)&ncount);
}
return 0;
}
函式InterlockIncrement阻塞其它的執行緒,當計數器遞增時防止其它的執行緒訪問nCount。
2.利用訊息實現輔助執行緒和主執行緒的通訊:
主執行緒有一個視窗,有訊息迴圈,我們可以在呼叫AfxBeginThread時把視窗控制程式碼傳遞給輔助執行緒,我們透過post方式傳遞訊息,在函式退出時,給視窗傳送一個訊息。
重新編寫執行緒函式如下:
int nCount=0;
UINT ThreadProc(LPVOID pParam)
{
while(nCount<500)
{
::InterlockedIncrement((long*)&ncount);
Add(nCount);
}
::PostMessage(
(HWND)pParam,
WM_THREADFINISHED,//使用者自定義訊息
0,0);
return 0;
}
編寫OnStart函式:
void CThreadDlg::OnStart()
{
m_nTimer=SetTimer(1,100,NULL);//0.1秒
ASSERT(m_nTimer!=0);
GetDlgItem(IDC_START)->EnableWindow(FALSE);
AfxBeginThread(ThreadProc,GetSafeHwnd(),THREAD_PROIRITY_NOMAL);
}
編輯OnCancel函式如下:
void CThreadDlg::OnCancel()
{
if(nCount==0)
CDialog::OnCancel();
else nCount=500;
}
處理OnThreadFinished函式
HRESULT CThreadDlg::OnThreadFinished(WPARAM wParam,LPARAM lParam)
{
CDialog::OnOk();
return 0;
}
3.用事件使執行緒同步:
利用WaitForSingle函式
在stdafx.h中寫入下面一行
#include//由於使用了事件
宣告兩個全域性變數
CEvent m_start,m_kill;
在初始化函式中啟動執行緒;
重新編寫OnStart函式:
void CThreadDlg::OnStart()
{
m_nTimer=SetTimer(1,100,NULL);//0.1秒
ASSERT(m_nTimer!=0);
GetDlgItem(IDC_START)->EnableWindow(FALSE);
m_start.SetEvent();
}
重新編輯OnCancel函式如下:
void CThreadDlg::OnCancel()
{
if(nCount==0)
m_start.SetEvent();
else m_kill.SetEvent();
}
編寫全域性函式如下:
UINT ThreadProc(LPVOID pParam)
{
::WaitForSingleObject(m_start,INFINITE);
while(nCount<500)
{
Add(nCount);
if(::WaitForSingleObject(m_start,0)=WAIT_OBJECT_0)
break;
}
::PostMessage(
(HWND)pParam,
WM_THREADFINISHED,//使用者自定義訊息
0,0);
return 0;
}
其中第一個WaitForSingleObject的呼叫等待啟動事件,INFINITE使其等待直到啟動事件有訊號。第二個呼叫若有訊號,立即返回,中止執行緒。
提供兩種執行緒,介面執行緒和輔助執行緒。使用者介面執行緒有視窗,因此有自己的訊息迴圈,輔助執行緒沒有視窗,不需要處理訊息。但是輔助執行緒非常有用而且很容易,比如程式在某個執行時間要完成多個(很笨重的)任務時,顯然,輔助執行緒的使用會使程式的執行大大的提高。但是,執行緒間的通訊是一個必須解決的問題。
下面我們就來討論一下執行緒間的通訊的問題:
一.執行緒的管理
1.執行緒的啟動:
在使用輔助執行緒時,我們必須為執行緒寫一個全域性函式,它的返回值必須為 UINT型別,而且必須有LPVOID型別的引數,啟動執行緒下面的函式:
CWinThread* pThread=AfxBeginThread(
AFX_THREADPPOC ThreadProc,
LPVOID pParam,
int nPriority,
UINT nStackSize,
D dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs);
全域性函式必須定義為 UINT ThreadProc(LPVOID pParam);
AfxBeginThread會立即返回一個指向新建立的執行緒的指標,用來管理線 程,包括掛起和恢復執行緒的執行,但是執行緒物件沒有成員函式來中止執行緒的運 行。AfxBeginThread的第二個引數是一個32位的值,用來傳給全域性函式;第三 個引數用來設定執行緒的優先順序;而第四和第六個引數用來指定執行緒堆疊大小和 性,一般採用預設值0;第五個引數用來設定建立執行緒物件的方式,0為立 即執行,CREATE_SUSPEND為執行緒透過ResumeThread後才執行。
而執行緒優先順序的設定和獲得可以透過下面的兩個函式來實現:
pThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NOMAL);和
int nPriority=pThread->GetThreadPriority();
2.執行緒的中止:
可以呼叫MFC的AfxEndThread函式;
3.檢查執行緒是否結束:
呼叫函式GetExitCodeThread,
DWORD ExitCode ;
::GetExitCodeThread(pThread->m_hThread,&ExitCode );
if(ExitCode==STILL_ACTIVE)
//執行中
else //執行緒已經中止
二.主執行緒和輔助執行緒的通訊
主執行緒和輔助執行緒間的通訊方式有很多種,最簡單的就是利用全域性變數。 這裡利用訊息通訊是行不通的,因為輔助執行緒沒有訊息迴圈,不能夠利用 Windows訊息。
下面我們用一個例子來說明。在例子中,我們寫一個非常笨的函式,如實 現500*3000*3000的加法資料處理函式Add(int nCount);
我們在對話方塊上放置Start、Cancel按鈕和一個用來表示資料處理進度的進度條 。
1.利用全域性變數來實現主執行緒和輔助執行緒的通訊:
我們編寫全域性函式如下:
UINT ThreadProc(LPVOID pParam)
{
nCount=0;//全域性變數
while(nCount<500)
{
Add(nCount);
::InterlockedIncrement((long*)&ncount);
}
return 0;
}
函式InterlockIncrement阻塞其它的執行緒,當計數器遞增時防止其它的執行緒訪問nCount。
2.利用訊息實現輔助執行緒和主執行緒的通訊:
主執行緒有一個視窗,有訊息迴圈,我們可以在呼叫AfxBeginThread時把視窗控制程式碼傳遞給輔助執行緒,我們透過post方式傳遞訊息,在函式退出時,給視窗傳送一個訊息。
重新編寫執行緒函式如下:
int nCount=0;
UINT ThreadProc(LPVOID pParam)
{
while(nCount<500)
{
::InterlockedIncrement((long*)&ncount);
Add(nCount);
}
::PostMessage(
(HWND)pParam,
WM_THREADFINISHED,//使用者自定義訊息
0,0);
return 0;
}
編寫OnStart函式:
void CThreadDlg::OnStart()
{
m_nTimer=SetTimer(1,100,NULL);//0.1秒
ASSERT(m_nTimer!=0);
GetDlgItem(IDC_START)->EnableWindow(FALSE);
AfxBeginThread(ThreadProc,GetSafeHwnd(),THREAD_PROIRITY_NOMAL);
}
編輯OnCancel函式如下:
void CThreadDlg::OnCancel()
{
if(nCount==0)
CDialog::OnCancel();
else nCount=500;
}
處理OnThreadFinished函式
HRESULT CThreadDlg::OnThreadFinished(WPARAM wParam,LPARAM lParam)
{
CDialog::OnOk();
return 0;
}
3.用事件使執行緒同步:
利用WaitForSingle函式
在stdafx.h中寫入下面一行
#include
宣告兩個全域性變數
CEvent m_start,m_kill;
在初始化函式中啟動執行緒;
重新編寫OnStart函式:
void CThreadDlg::OnStart()
{
m_nTimer=SetTimer(1,100,NULL);//0.1秒
ASSERT(m_nTimer!=0);
GetDlgItem(IDC_START)->EnableWindow(FALSE);
m_start.SetEvent();
}
重新編輯OnCancel函式如下:
void CThreadDlg::OnCancel()
{
if(nCount==0)
m_start.SetEvent();
else m_kill.SetEvent();
}
編寫全域性函式如下:
UINT ThreadProc(LPVOID pParam)
{
::WaitForSingleObject(m_start,INFINITE);
while(nCount<500)
{
Add(nCount);
if(::WaitForSingleObject(m_start,0)=WAIT_OBJECT_0)
break;
}
::PostMessage(
(HWND)pParam,
WM_THREADFINISHED,//使用者自定義訊息
0,0);
return 0;
}
其中第一個WaitForSingleObject的呼叫等待啟動事件,INFINITE使其等待直到啟動事件有訊號。第二個呼叫若有訊號,立即返回,中止執行緒。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987652/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 程式通訊 執行緒通訊執行緒
- Java多執行緒-執行緒通訊Java執行緒
- 執行緒4--執行緒間通訊執行緒
- Java執行緒通訊Java執行緒
- Java多執行緒學習——執行緒通訊Java執行緒
- libuv執行緒通訊執行緒
- Java之執行緒通訊Java執行緒
- 執行緒間的通訊執行緒
- 徹底明白Java的多執行緒-執行緒間的通訊(2)(轉)Java執行緒
- 徹底明白Java的多執行緒-執行緒間的通訊(1)(轉)Java執行緒
- java多執行緒5:執行緒間的通訊Java執行緒
- 多執行緒之間通訊及執行緒池執行緒
- Java多執行緒學習(3)執行緒同步與執行緒通訊Java執行緒
- 子執行緒與UI執行緒的通訊(委託)執行緒UI
- JUC執行緒高階---執行緒控制通訊Condition執行緒
- Android執行緒間通訊Android執行緒
- 深入理解執行緒通訊執行緒
- 多執行緒Demo學習(執行緒的同步,簡單的執行緒通訊)執行緒
- 執行緒池原理初探執行緒
- 說說Java執行緒間通訊Java執行緒
- Android中的執行緒通訊Android執行緒
- JUC之執行緒間的通訊執行緒
- 多執行緒之間的通訊執行緒
- java多執行緒間的通訊Java執行緒
- flutter: 執行緒通訊與訊息迴圈Flutter執行緒
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- JavaSE_多執行緒入門 執行緒安全 死鎖 狀態 通訊 執行緒池Java執行緒
- 多執行緒、重疊I/O的通訊埠元件 (轉)執行緒元件
- Java中利用管道實現執行緒間的通訊(轉)Java執行緒
- .NET下多執行緒初探執行緒
- 使用Windows API和多執行緒進行串列埠通訊[1] (轉)WindowsAPI執行緒串列埠
- Java執行緒(九):Condition-執行緒通訊更高效的方式Java執行緒
- Java多執行緒/併發11、執行緒同步通訊:notify、waitJava執行緒AI
- Java-執行緒間通訊小結Java執行緒
- iOS GCD執行緒之間的通訊iOSGC執行緒
- 執行緒通訊舉例1 管程法執行緒
- 執行緒間通訊_等待/通知機制執行緒
- JavaThread多執行緒同步、鎖、通訊Javathread執行緒