Winform实现多线程异步更新UI(进度及状态信息)

引言

在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验。所以在大量数据操作的应用上,需要使用多线程来处理这种情况。在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单。本文实现了用子线程去处理数据,并实时更新主线程的ui状态了。下面就开始一步步的去实现异步线程更新ui的demo程序吧。

应用背景 


写入一定量的数据到文本文件中,同时需要在主界面中反应出写入数据的实时进度情况。要求:需要将写入数据封装成一个类。

实现过程


1、首先建立一个winform项目,在主窗体上拖入一个button,一个progressbar,一个lable。如下图所示。

2、编写一个处理数据的类(WriteDate),源代码如下。
复制代码
  public class DataWrite
    {
        public delegate void UpdateUI(int step);//声明一个更新主线程的委托
        public UpdateUI UpdateUIDelegate;

        public delegate void AccomplishTask();//声明一个在完成任务时通知主线程的委托
        public AccomplishTask TaskCallBack;
       
        public void Write(object lineCount)
        {
            StreamWriter writeIO = new StreamWriter("text.txt", false, Encoding.GetEncoding("gb2312"));
            string head = "编号,省,市";
            writeIO.Write(head);
            for (int i = 0; i < (int)lineCount; i++)
            {
                writeIO.WriteLine(i.ToString() + ",湖南,衡阳");
                //写入一条数据,调用更新主线程ui状态的委托
                UpdateUIDelegate(1);
            }
            //任务完成时通知主线程作出相应的处理
            TaskCallBack();
            writeIO.Close();
        }
    }
复制代码

 

3、主界面中的代码如下:
  首先要建立一个委托来实现非创建控件的线程更新控件。
 delegate void AsynUpdateUI(int step);

 

   然后编写多线程去启动写入数据的方法以及回调的函数。

复制代码
     private void btnWrite_Click(object sender, EventArgs e)
        {
            int taskCount = 10000; //任务量为10000
            this.pgbWrite.Maximum = taskCount;
            this.pgbWrite.Value = 0;

            DataWrite dataWrite = new DataWrite();//实例化一个写入数据的类
            dataWrite.UpdateUIDelegate += UpdataUIStatus;//绑定更新任务状态的委托
            dataWrite.TaskCallBack += Accomplish;//绑定完成任务要调用的委托

            Thread thread = new Thread(new ParameterizedThreadStart(dataWrite.Write));
            thread.IsBackground = true;
            thread.Start(taskCount);
        }

        //更新UI
        private void UpdataUIStatus(int step)
        {
            if (InvokeRequired)
            {
                this.Invoke(new AsynUpdateUI(delegate(int s)
                {
                    this.pgbWrite.Value += s;
                    this.lblWriteStatus.Text = this.pgbWrite.Value.ToString() + "/" + this.pgbWrite.Maximum.ToString();
                }), step);
            }
            else
            {
                this.pgbWrite.Value += step;
                this.lblWriteStatus.Text = this.pgbWrite.Value.ToString() + "/" + this.pgbWrite.Maximum.ToString();
            }
        }

        //完成任务时需要调用
        private void Accomplish()
        {
            //还可以进行其他的一些完任务完成之后的逻辑处理
            MessageBox.Show("任务完成");
        }
复制代码
效果如下:
 
总结

实现异步更新ui有很多种方法,但是我认为这种方式是比较灵活,能实时的获取到任务进行的状态,并且对之进行相应的处理。这种模式还适用于使用多个线程同时写入不同的数据到不同的文件中去。
源代码下载地址:http://download.csdn.net/detail/mingge38/9378852

来源: Winform实现多线程异步更新UI(进度及状态信息) - msay - 博客园

weinxin
我的微信
一个码农、工程狮、集能量和智慧于一身的、DIY高手、小伙伴er很多的、80后奶爸。
Igor
  • 版权声明: 发表于 2019-03-0518:06:03
  • 转载注明:http://blog.tsingmac.com/prolions/codelanguage/mscs/1699/
Dapper的异步方式使用学习 C/C++/C#

Dapper的异步方式使用学习

Dapper异步使用学习 Dapper已经赢得了C#轻量级ORM的王者称号,但却被很多人认为是一款用于.Net环境的简单的对象映射器。当人们希望自己编写具有最佳性能的SQL查询时,他们会更喜欢Dapp...
如何使用 Dapper 中的异步方法 C/C++/C#

如何使用 Dapper 中的异步方法

Dapper 是一个 容易上手,轻量级,灵活高效,开源的 迷你 ORM,由 Stack Overflow 团队的 Sam Saffron 出品,你可以利用 Dapper 简化数据访问并且支持高性能, ...
c# - 异步使用MySQL DB C/C++/C#

c# – 异步使用MySQL DB

C#异步读取MySQL数据库的问题解决。 我试图了解异步使用数据库。为此,我用一个表创建了简单的MySQL数据库,然后可以通过以下方式从中获取信息: public static void SyncRe...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: