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

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


感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接
  • 3
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Winform中,更新UI是一个常见的需求。通常情况下,UI更新是在主线程(也称为UI线程)中完成的。但某些情况下,当我们需要进行一些耗时的操作时,如果在主线程中进行,可能会导致UI的卡顿或无响应。这时就需要使用异步更新UI的方式。 异步更新UI可以通过多线程或者使用异步操作方法来实现。其中,通过使用异步操作方法是比较常见的方式。 在Winform中,可以使用async和await关键字来定义异步操作。在函数或方法前面使用async关键字进行标识,然后在需要异步执行的代码块前使用await关键字进行标识。这样就可以将这部分代码放在一个单独的任务中,不会影响主线程的执行。 以一个例来说明,假设我们需要在按钮点击时执行一个耗时的操作,然后将结果显示在Label控件上。 首先,我们需要在按钮的Click事件处理程序中标识为异步操作: ``` private async void Button_Click(object sender, EventArgs e) { await Task.Run(() => { // 执行耗时操作,例如数据库查询或网络请求 string result = SomeLongRunningOperation(); // 在UI线程更新UI Invoke(new Action(() => { labelResult.Text = result; })); }); } ``` 在上述代码中,我们使用Task.Run方法创建了一个后台任务,并将耗时操作代码放在其中。然后,在任务完成后通过Invoke方法将结果更新UI控件中。Invoke方法将会将UI操作投递到UI线程执行,确保线程安全性。 通过这种方式,当点击按钮时,耗时操作将在后台执行,不会阻塞主线程,保持UI的流畅性。同时,等待任务完成后,会将结果更新UI控件上,实现异步更新UI的效果。 需要注意的是,在异步更新UI时,应该确保对UI线程的访问是线程安全的,可以使用Invoke或BeginInvoke等方法来实现。否则可能会导致线程冲突或其他问题。 总结起来,Winform异步更新UI可以通过使用async和await关键字,结合Task.Run和Invoke等方法来实现。这样可以在耗时操作完成后,将结果异步更新UI上,提升用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值