• 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线程操作控件产生的异常。

  • 相关阅读:
    Python爬虫基础之BeautifulSoup
    Python爬虫基础之requests
    Python爬虫基础之UrlError
    Python爬虫基础之Cookie
    module 'socket' has no attribute的解决方案
    ECS——CentOS7下使用yum安装MariaDB
    用 Python 定位特定类型文件
    django——文本编辑器
    解决文件路径的问题的总结
    Django——发送邮件
  • 原文地址:https://www.cnblogs.com/yelanggu/p/6996349.html
Copyright © 2020-2023  润新知