C#中的Invoke和BeginInvoke

1、Control#Invoke() 和Control#BeginInvoke()

在非UI線程中調用MessageBox.Show()結果是非模態對話框;
在UI線程中調用MessageBox.Show()結果是模態對話框。
也就是說,MessageBox的模態仍是非模態控制的是它所在的那個線程!一旦使用MessageBox,它就阻塞了它所在的那個線程。編程

在非UI線程中調用System.Forms.Timer#Start方法無論用,在UI線程中才管用。網絡

以上兩個例子引出今日的主角:Control#Invoke()和Control#BeginInvoke()併發

  • Invoke和BeginInvoke函數使得非UI線程能夠方便地把任務放到UI線程中去執行
  • 在UI線程中調用Invoke和BeginInvoke這兩個函數是沒有意義的,這兩個函數只能在非UI線程中調用
    由於它倆的做用就是非UI線程將任務交給UI線程去執行
  • 這兩個函數的區別是:Invoke會阻塞非UI線程;BeginInvoke不會阻塞非UI線程

在編程中,耗時的任務(好比IO,網絡請求等)是不容許放在UI線程中的。這一點在一切界面編程中老是成立的。在桌面編程中,從沒有庫明確禁止耗時任務放在UI線程中。你能夠把耗時的任務放在UI線程中,並無錯誤,只是難受的是本身。而Android中明確規定UI線程中禁止網絡請求,不然會拋出異常。
當耗時任務結束以後,一般須要更新界面,這時,Invoke和BeginInvoke這兩個函數就派上大用了。異步

以上兩個問題的解決方案:使用Invoke調用MessageBox.Show()和timer.Start().
this.Invoke(new Action(delegate{}));

2、委託的Invoke和BeginInvoke

string haha(string s) {
        return s + s.Length;
    }
    delegate string h(string s);//定義一個函數指針類型
    Haha() {
        h ha = haha;
        IAsyncResult res = ha.BeginInvoke("weidiao", null, null);
        string ans = ha.EndInvoke(res);//此處會阻塞
        Console.WriteLine(ans);
    }

IAsyncResult.IsCompleted屬性能夠判斷任務是否執行完畢。函數

IAsyncResult res = ha.BeginInvoke("weidiao", null, null);
        while (res.IsCompleted == false) {
            Console.Write("*");
            Thread.Sleep(500);
        }
        string ans = ha.EndInvoke(res);

IAsyncResult.AsyncWaitHandle屬性可使當前線程(主調線程)等待一段時間。WaitOne的第一個參數表示要等待的毫秒數,在指定時間以內,WaitOne方法將一直等待,直到異步調用完成,併發出通知,WaitOne方法才返回true。當等待指定時間以後,異步調用仍未完成,WaitOne方法返回false,若是指定時間爲0,表示不等待,若是爲-1,表示永遠等待,直到異步調用完成。this

h ha = haha;
        IAsyncResult res = ha.BeginInvoke("weidiao", null, null);
        while (!res.AsyncWaitHandle.WaitOne(500)) {
            Console.Write("*");
        }
        string ans = ha.EndInvoke(res);
        Console.WriteLine(ans);

使用回調函數線程

using System;
using System.Threading;
using System.Windows.Forms;
class Haha {
    string haha(string s) {
        Thread.Sleep(3000);
        return s + s.Length;
    }
    delegate string h(string s);
    void callback(IAsyncResult res) {
        Console.Write(ha.EndInvoke(res));
    }
    h ha ;
    Haha() {
        ha = haha;
        IAsyncResult res = ha.BeginInvoke("haha", new AsyncCallback(callback), null);
    }
    static void Main() {
        new Haha();
        Application.Run(new Form());
    }
}
相關文章
相關標籤/搜索