程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 線程系列10,無需顯式調用線程的情形,線程情形

線程系列10,無需顯式調用線程的情形,線程情形

編輯:C#入門知識

線程系列10,無需顯式調用線程的情形,線程情形


通常,我們會通過線程的構造函數先創建線程再使用線程。而實際上,.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上。

 

線程系列包括:

線程系列01,前台線程,後台線程,線程同步

線程系列02,多個線程同時處理一個耗時較長的任務以節省時間

線程系列03,多線程共享數據,多線程不共享數據

線程系列04,傳遞數據給線程,線程命名,線程異常處理,線程池

線程系列05,手動結束線程

線程系列06,通過CLR代碼查看線程池及其線程

線程系列07,使用lock語句塊或Interlocked類型方法保證自增變量的數據同步

線程系列08,實現線程鎖的各種方式,使用lock,Montor,Mutex,Semaphore以及線程死鎖

線程系列09,線程的等待、通知,以及手動控制線程數量

線程系列10,無需顯式調用線程的情形


對於N個線程等待執行

#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個線程運行....余下全文>>
 

java 線程

就是在主線程創建10個線程,保留各個線程引用(最好使用集合)然後分別start,再調用各個線程的join方法,這樣下面代碼就會在那10個線程全部結束之後在運行。然後再創建10個線程(建議用循環)
 

  1. 上一頁:
  2. 下一頁: