c# 委托與異步調用


  背景:在winform UI中,有時需要對控件進行比較頻繁的刷新,如進度條、picturebox顯示視頻等。如果在主線程進行這些刷新操作,操作還未完成就將執行下一次刷新,程序將發生錯誤;如果只是創建另一個線程執行這些操作,將和主線程產生競爭,造成界面鎖死(因此windows GUI編程有一個規則,就是只能通過創建控件的線程來操作控件的數據,否則就可能產生不可預料的結果)。這時候,我們就可以用委托與異步來解決這個問題。

  委托:回顧一下委托 ,一、定義委托,委托定義的參數與傳遞給委托的方法的參數一致。二、聲明與實例化。三、調用,將委托作為參數供方法調用。 

  異步:Windows窗體控件,唯一可以從創建它的線程之外的線程中調用的是Invoke()、BeginInvoke()、EndInvoke()方法和InvokeRequired屬性。這些方法會切換到創建控件的線程上,以調用賦予一個委托參數的方法,該委托參數可以傳遞給這些方法。

    關於Invoke()與BeginInvoke():其中BeginInvoke()、EndInvoke()方法是Invoke()方法的異步版本。相同點:都需要一個委托對象作為參數。不同點:Invoke()是同步方法,Invoke封送的方法被執行完畢前,Invoke()不會返回,從而調用者線程將被阻塞;需要等待UI操作執行完畢后繼續執行線程時考慮使用。而BeginInvoke()相反,是異步方法,方法調后立即返回,不用等待委托方法的執行結束,主線程就不會阻塞。

    Delegate.BeginInvoke方法從ThreadPool取出一個線程來執行這個方法,以獲得異步執行效果。Control.BeginInvoke方法並不會另開線程。

  參考:http://blog.csdn.net/stxyc/article/details/16945581

  初學C#,理解的不是很透徹,一步一步來,循序漸進。

  下面是一個進度條的小程序:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace progressBar
{
    public partial class Form1 : Form
    {
        delegate void ShowProgressDelegate();
        delegate void RunTaskDelegate();

        public Form1()
        {
            InitializeComponent();

            this.progressBar1.Maximum = 50;
            this.progressBar1.Step = 1;
        }

        private void startBtn_Click(object sender, EventArgs e)
        {
            RunTaskDelegate runTask = new RunTaskDelegate(RunTask);
            // 委托異步調用方法
            runTask.BeginInvoke(null, null);
        }

        private void closeBtn_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        //進度條增加
        void ShowProgress()
        {
               this.progressBar1.PerformStep();
        }

        //模擬工作方法
        public void RunTask()
        {
            ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress);

            int iTotal = 50;//工作量
            for (int i = 0; i < iTotal; i++)
            {
                System.Threading.Thread.Sleep(1000);//模擬工作 
                this.BeginInvoke(showProgress);
            }
        }
       
    }
}

   我目前的理解是:RunTaskDelegate的作用是從另一個線程調用RunTask()方法(此方法中包含主線程的休眠),可以避免休眠期間界面無響應。ShowProgressDelegate的作用就是異步調用ShowProgress()方法,從而避免非UI線程操作控件產生的異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM