1. 程式人生 > >System.Windows.Forms.Control.Invoke與BeginInvoke

System.Windows.Forms.Control.Invoke與BeginInvoke

info lib 示例 完成 sync read flink ring 由於

WinForm的UI對象只能在UI線程中操作,在非UI線程中操作UI對象,會引發不可預知的錯誤,這時就需要用到Control.Invoke或者Control.BeginInvoke。

用戶線程調用Control.BeginInvoke會向UI消息隊列發送一個帶委托消息,Control.BeginInvoke不會阻塞用戶線程,直接返回IAsyncResult對象。

用戶線程調用Control.EndInvoke(IAsyncResult),Control.EndInvoke會阻塞用戶線程,直到委托執行完成,並返回委托的返回值。沒有返回值返回null。

Control.Invoke相當於Control.BeginInvoke和Control.EndInvoke的合體,會阻塞用戶線程,直到委托執行完成,並返回委托的返回值。沒有返回值返回null。

根據類繼承關系,在窗口中可以直接使用BeginInvoke、EndInvoke、Invoke。

System.Object
??System.MarshalByRefObject
????System.ComponentModel.Component
??????System.Windows.Forms.Control
????????System.Windows.Forms.ScrollableControl
??????????System.Windows.Forms.ContainerControl
????????????System.Windows.Forms.Form

實驗示例:

窗體:

技術分享圖片

代碼:

技術分享圖片
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 在非UI線程中操作UI對象,調試運行會報錯。
            // 直接運行會使程序置於不可預知風險之中。
            new Thread(() =>
            {
                progressBar1.Value 
= 100; }).Start(); } private void button2_Click(object sender, EventArgs e) { new Thread(() => { var result = this.Invoke(new Func<int, int, string>((n1, n2) => { for(int i = 0; i <= 100; i += 10) { progressBar1.Value = i; Thread.Sleep(200); } return (n1+n2).ToString(); }), 100, 21); MessageBox.Show(result.GetType().ToString() + ":" + result); }).Start(); } private void button3_Click(object sender, EventArgs e) { new Thread(() => { IAsyncResult asyncResult = this.BeginInvoke(new Func<int, int, string>((n1, n2) => { for (int i = 0; i <= 100; i += 10) { progressBar1.Value = i; Thread.Sleep(200); } return (n1 + n2).ToString(); }), 200, 32); MessageBox.Show("BeginInvoke不會阻塞"); var result = this.EndInvoke(asyncResult); MessageBox.Show("EndInvoke會阻塞," + result.GetType().ToString() + ":" + result); }).Start(); } private void button4_Click(object sender, EventArgs e) { // 連續給兩個委托,由於UI線程只有一個,兩個委托只能先後執行 new Thread(() => { IAsyncResult asyncResult1 = this.BeginInvoke(new Func<int, int, string>((n1, n2) => { for (int i = 0; i <= 100; i += 10) { progressBar1.Value = i; Thread.Sleep(200); } return (n1 + n2).ToString(); }), 200, 32); IAsyncResult asyncResult2 = this.BeginInvoke(new Func<int, int, string>((n1, n2) => { for (int i = 0; i <= 100; i += 10) { progressBar2.Value = i; Thread.Sleep(200); } return (n1 + n2).ToString(); }), 400, 64); MessageBox.Show("BeginInvoke不會阻塞"); var result1 = this.EndInvoke(asyncResult1); MessageBox.Show("EndInvoke(asyncResult1)返回"); var result2 = this.EndInvoke(asyncResult2); MessageBox.Show("EndInvoke(asyncResult2)返回"); MessageBox.Show( result1.GetType().ToString() + ":" + result1 + "\r\n" + result2.GetType().ToString() + ":" + result2); }).Start(); } private void button5_Click(object sender, EventArgs e) { // 要等精度條更新完成後,點擊才能響應 MessageBox.Show("ha"); } private void button6_Click(object sender, EventArgs e) { progressBar1.Value = 0; progressBar2.Value = 0; } }
View Code

System.Windows.Forms.Control.Invoke與BeginInvoke