C# 使用委託實現多線程調用表單

來源:互聯網
上載者:User

C#多線程函數如何傳參數和傳回值 

提起多線程,不得不提起 委託(delegates)這個概念.

我理解的委託就是 具有 同樣參數和傳回值 的函數的集合.
比如

public delegate void MyDelegate(int arg);就是這種形式的函數 void Myfuntion(int i); 的集合.如何將一個函數加入 委託 的集合?MyDelegate dele = new MyDelegate(Myfuntion1);再增加一個dele += new MyDelegate(Myfuntion2);

  

...
委託函數 dele 就是 具有整數參數和空傳回值的函數 Myfuntion1,2的集合.
調用這個委託函數
dele(1);
就是逐個調用 Myfuntion1,2,...

一般線程函數的聲明和啟動

Thread t = new Thread(new ThreadStart(MyFunction));t.Start();

  

正是調用了沒有參數和傳回值的 委託函數 ThreadStart
其中的參數MyFunction 是 這個委託函數中的一員.

很明顯 這樣無法傳參數和傳回值,那我們該怎麼辦?

答案就在委託 的BeginInvoke() 方法上, BeginInvoke() 也是(非同步)啟動一個新線程.
例如

MyDelegate dele = new MyDelegate (MyFunction);dele.BeginInvoke(10,"abcd");void MyFunction(int count, string str);

  

可以實現參數的傳遞.

如何收集線程函數 的 傳回值?

與 BeginInvoke 對應 有個 EndInvoke 方法,而且運行完畢返回 IAsyncResult 類型的傳回值.
這樣我們可以這樣收集 線程函數的 傳回值

MyDelegate dele = new MyDelegate (MyFunction);IAsyncResult ref = dele.BeginInvoke(10,"abcd");...int result = dele.EndInvoke(ref); <----收集 傳回值int MyFunction(int count, string str); <----帶參數和傳回值的 線程函數

  

 

提示:"線程間操作無效:從不是建立控制項“XX”的線程訪問它"

一般來說,直接在子線程中對表單上的控制項操作是會出現異常,這是由於子線程和運行表單的線程是不同的空間,因此想要在子線程來操作表單上的控制項,是不可能簡單的通過控制項對象名來操作,但不是說不能進行操作,微軟提供了Invoke的方法,其作用就是讓子線程告訴表單線程來完成相應的控制項操作。 現在用一個用線程式控制制的進程條來說明,大致的步驟如下:

1. 建立Invoke函數,大致如下: /// /// Delegate function to be invoked by main thread ///private void InvokeFun(){ if( prgBar.Value < 100 )prgBar.Value = prgBar.Value + 1; }2. 子線程入口函數: /// /// Thread function interface ///private void ThreadFun(){ //Create invoke method by specific functionMethodInvoker mi = new MethodInvoker( this.InvokeFun );for( int i = 0; i < 100; i++ ) { this.BeginInvoke( mi ); Thread.Sleep( 100 ); } }3. 建立子線程:Thread thdProcess = new Thread( new ThreadStart( ThreadFun ) );thdProcess.Start(); 出現這個問題主要是因為線上程方法中操作了介面上的控制項..lstPrime.Items.Add() 可以這樣改下.. //定義一個委託 public delegate void MyInvoke(string str); //定義一個操作介面的方法 private void UpdateUI(string str) {    //增加項    this.lstPrime.Items.Add(str); } //線上程的方法中,即你的Generate方法.. //裡面只要是涉及到Items.Add操作的都改成如下形式即可.. //比如lstPrime.Items.Add(2);改成: MyInvoke mi=new MyInvoke(UpdateUI); this.BeginInvoke(mi,new object[]{ "2 "}); 

  

============================================================================

BeginInvoke與Invoke的含義[轉載]BeginInvoke 方法真的是新開一個線程進行非同步呼叫嗎? 

參考以下代碼: 

public delegate void treeinvoke(); 
private void UpdateTreeView() 

MessageBox.Show(System.Threading.Thread.CurrentThread.Name); 

private void button1_Click(object sender, System.EventArgs e) 

System.Threading.Thread.CurrentThread.Name = "UIThread"; 
treeView1.BeginInvoke(new treeinvoke(UpdateTreeView)); 

看看運行結果,彈出的對話方塊中顯示的是 UIThread,這說明 BeginInvoke 所調用的委託根本就是在 UI 線程中執行的。 

既然是在 UI 線程中執行,又何來“非同步執行”一說呢? 

我們再看看下面的代碼: 

public delegate void treeinvoke(); 
private void UpdateTreeView() 

MessageBox.Show(Thread.CurrentThread.Name); 

private void button1_Click(object sender, System.EventArgs e) 

Thread.CurrentThread.Name = "UIThread"; 
Thread th = new Thread(new ThreadStart(StartThread)); 
th.Start(); 

private void StartThread() 

Thread.CurrentThread.Name = "Work Thread"; 
treeView1.BeginInvoke(new treeinvoke(UpdateTreeView)); 

再看看運行結果,彈出的對話方塊中顯示的還是 UIThread,這說明什嗎?這說明 BeginInvoke 方法所調用的委託無論如何都是在 UI 線程中執行的。 

那 BeginInvoke 究竟有什麼用呢? 

在多線程編程中,我們經常要在背景工作執行緒中去更新介面顯示,而在多線程中直接調用介面控制項的方法是錯誤的做法,具體的原因可以在看完我的這篇之後看看這篇:在多線程中如何調用Winform,如果你是大牛的話就不要看我這篇了,直接看那篇吧,反正那篇文章我沒怎麼看懂。 

Invoke 和 BeginInvoke 就是為瞭解決這個問題而出現的,使你在多線程中安全的更新介面顯示。 

正確的做法是將背景工作執行緒中涉及更新介面的代碼封裝為一個方法,通過 Invoke 或者 BeginInvoke 去調用,兩者的區別就是一個導致背景工作執行緒等待,而另外一個則不會。 

而所謂的“一面響應操作,一面添加節點”永遠只能是相對的,使 UI 線程的負擔不至於太大而以,因為介面的正確更新始終要通過 UI 線程去做,我們要做的事情是在背景工作執行緒中包攬大部分的運算,而將對純粹的介面更新放到 UI 線程中去做,這樣也就達到了減輕 UI 線程負擔的目的了。 

而在那段更新樹節點的代碼中,其實唯一起作用的代碼是:System.Threading.Thread.Sleep(100);,它使 UI 線程有了處理介面訊息的機會,其實 數位幽靈 將問題複雜化了,只要以下的代碼就可以很好的工作了。 

private void button1_Click_(object sender, System.EventArgs e) 

TreeNode tn; 
for(int i=0;i<100000;i++) 

tn=new TreeNode (i.ToString()); 
this.treeView1.Nodes[0].Nodes.Add(tn); 
if (i%100 == 0) Application.DoEvents(); 

}

為了您的安全,請只開啟來源可靠的網址 

開啟網站    取消

來自: http

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.