通常,我們會通過線程的構造函數先創建線程再使用線程。而實際上,.NET中有些類提供的方法,其內部就是使用多線程處理的。一些封裝了多線程、異步處理方法的類都符合了"事件驅動異步模式(event-based asynchronous pattern)"。以System.ComponentModel下的BackgroundWorker類來說,該類就符合這種模式。
BackgroundWorker類屬性:
WorkerSupportsCancellation:設置為true表示允許取消
WorkerReportProgress:設置為true表示可顯示進度
BackgroundWorker類事件:
DoWork:後台線程要做的事
ProgressChanged:進度觸發事件
RunWorkerCompleted:當進度結束、拋出異常、或取消執行時觸發
舉例,在Windows窗體應用程序中使用BackgroundWorker類。
→新建一個Windows窗體應用程序,界面包括2個button,1個label,1個progressbar,1個BackgournWorker控件。
→設置BackgournWorker控件的WorkerSupportsCancellation屬性和WorkerReportProgress為true。
→後台代碼為:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e){int sum = 0;for (int i = 1; i <=100; i++){Thread.Sleep(1000);sum = sum + 1;backgroundWorker1.ReportProgress(i);//如果取消計算if (backgroundWorker1.CancellationPending){e.Cancel = true;backgroundWorker1.ReportProgress(0);return;}e.Result = sum;}}private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e){//把BackgroundWorker的進程體現到ProgressBar上progressBar1.Value = e.ProgressPercentage;//把BackgroundWorker的進程體現到label上label1.Text = e.ProgressPercentage + "%";}private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){if (e.Cancelled) //可能以取消的方式結束{label1.Text = "計算被取消";}else if (e.Error != null)//可能以拋出異常的方式結束{label1.Text = e.Error.Message;}else//可能正常結束{label1.Text = "1到100的和為:" + e.Result.ToString();}}//開始計算private void btnCalculate_Click(object sender, EventArgs e){if (!backgroundWorker1.IsBusy){backgroundWorker1.RunWorkerAsync();}}//取消計算private void btnCancel_Click(object sender, EventArgs e){if (backgroundWorker1.IsBusy){backgroundWorker1.CancelAsync();}}
在DoWork事件中:
○ BackgroundWorker的實例方法ReportProgress,用來把後台線程進展情況顯示到進度條。
○ 把DoWork的計算結果保存到DoWorkEventArgs類型的Result屬性中
在ProgressChanged事件中:
○ 把該事件的ProgressChangedEventArgs類型參數的ProgressPercentage屬性值分別顯示到進度條和label
在RunWorkerCompleted事件中:
○ 該事件的RunWorkerCompletedEventArgs類型參數的Cancelled屬性值用來判斷是否取消
○ RunWorkerCompletedEventArgs類型參數的Error屬性值用來記錄異常
○ RunWorkerCompletedEventArgs類型參數的Result屬性值取出在DoWork事件中,為DoWorkEventArgs類型的Result屬性設置的值
點擊"開始計算"按鈕,後台線程運行並顯示到進度條和label上。
線程系列包括:
線程系列09,線程的等待、通知,以及手動控制線程數量
#include "windows.h"
#include "iostream.h"
DWORD ThreadId[10];
HANDLE Thread[10];
int Operand=0;
int suffix;
int i=0;
CRITICAL_SECTION g_cs;
DWORD WINAPI ThreadProc(
LPVOID lpParameter
);
void CreateTh(DWORD suffix)
{
::CloseHandle(Thread[suffix]);
Thread[suffix]=CreateThread(NULL,0,ThreadProc,&suffix,0,&ThreadId[suffix]);
}
DWORD WINAPI ThreadProc(
LPVOID lpParameter
)
{
::EnterCriticalSection(&g_cs);
if(Operand>=1000)
return 0;
suffix=*(int*)lpParameter;
i=0;
while(i<100)
{
Operand++;
i++;
cout<<Operand<<endl;
::Sleep(100);
}
::LeaveCriticalSection(&g_cs);
CreateTh(suffix);
return 0;
}
int main(int argc, char* argv[])
{
InitializeCriticalSection(&g_cs);
for(int i=0;i<10;i++)
{
Thread[i]=::CreateThread(NULL,0,ThreadProc,&i,0,&ThreadId[i]);
}
::Sleep(1000);
WaitForMultipleObjects(10,Thread,true,INFINITE);
::DeleteCriticalSection(&g_cs);
for(i=0;i<10;i++)
::CloseHandle(Thread[i]);
printf("Hello,Word\n");
return 0;
}
我這裡有一個10000線程來遍歷計算機中所有的文件的例子.
我上面的思路是10個線程來處理同一件事,每當你個線程結束的
時候,以自己的線程編號和線程句柄來再創建一個線程,這樣就保
證系統裡面總有10個線程運行....余下全文>>
就是在主線程創建10個線程,保留各個線程引用(最好使用集合)然後分別start,再調用各個線程的join方法,這樣下面代碼就會在那10個線程全部結束之後在運行。然後再創建10個線程(建議用循環)