程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C#中跨線程操作控件(3)

C#中跨線程操作控件(3)

編輯:關於C語言

三、Thread/ThreadStart下的跨線程操作控件

在一些情況下,Thread/ThreadStart也是有一定市場的,特別在工作線程很多的情況下,顯得尤為突出。事實上,在這種環境下要實現上述 的例子並不難,代碼也沒有增加多少,前提是你必須理解Control.Invoke方法。該方法在MSDN上的解釋是:在擁有此控件的基礎窗口句柄的線 程上執行委托。如果你注意到了第一張圖片顯示的異常信息,你會很快理解這個方法的重大意義。它可以讓工作線程的中委托在主線程中執行 !因此實現上述例子的思路就是,在工作線程中使用委托來執行操作控件的方法,然後用主窗口的Invoke方法調用!為了實現 BackgroundWorker的ProgressChanged和RunWorkerCompleted事件,定義了ReportProcessInfo委托和DoneAfterCompleted委托。主要代碼如下 :

1//實現BackgroundWorker的ProgressChanged事件
2public delegate void ReportProcessInfo(string Info, int iPercent);
3/**/////實現BackgroundWorker的RunWorkerCompleted事件
4public delegate void DoneAfterCompleted(string Info);
5
6//更新ListvIEw和ProgressBar的方法
7    private void UpdateInfoToUser(string info,int percent)
8    {
9      if (InvokeRequired)
10        Invoke(new ReportProcessInfo(UpdateInfoToUser), info, percent);
11      else
12      {
13        lvOutput.Items.Add(new ListVIEwItem(new string[] { System.DateTime.Now.ToLongTimeString(), info })).EnsureVisible();
14        tssbProcess.Value = percent;
15      }
16       
17    }
18    //清空源目錄和目標目錄信息,顯示拷貝文件數的方法
19    private void ShowUserFilesCountInfo(string info)
20    {
21      if (InvokeRequired)
22        Invoke(new DoneAfterCompleted(ShowUserFilesCountInfo), info);
23      else
24      {
25        tbSource.Text = string.Empty;
26        tbTargetDir.Text = string.Empty;
27MessageBox.Show(info);
28      }
29      
30    }
31//線程函數
32private void CopyFiles(object SourceDir)
33    {
34      DirectoryInfo di = (DirectoryInfo)SourceDir;
35      int icur = 0;
36      foreach (FileInfo fi in di.GetFiles())
37      {
38        icur++;
39        tsslInfo.Text = string.Format("當前正在處理文件:{0}",fi.Name);
40        fi.CopyTo(Path.Combine(targetDir,fi.Name),true);
41        CopyOneFileIsOK(fi.Name,GetPercent(icur,iFileCount));
42      }
43      CopyFilesIsCompleted(string.Format("本次操作共拷貝了{0}個文件!",icur));
44    }
45

運行結果如下:

四、結尾

代碼中的InvokeRequired用於判斷該段代碼是否是在其他線程中委托調用的,如果為真,就需要在本線程中重新創建一個該委托的實例,並 用Invoke方法調用它,讓這段代碼在本線程中調用。

當代碼中需要對多個控件進行操作,最好使用Form的InvokeRequired來判斷,並使用Form的Invoke方法調用新建的委托實例。當只對某個控 件操作時,就可以只用該控件的InvokeRequired和Invoke。比如tbSource,就可用tbSource.InvokeRequired和tbSource.Invoke。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved