C#中多线程修改UI

程序描述:

如图所示,点击”写入数据“按钮后,会启动一个线程,该线程往一个文件写10000数据,每写一行数据,同时更新主线程的UI

代码如下:

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

namespace threadUI
{
    public partial class Form1 : Form
    {
        delegate void AsyncUpdateUI(int step);
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_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);
        }
        private void UpdataUIStatus(int step)
        {
            if (InvokeRequired)
            {
                this.Invoke(new AsyncUpdateUI(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("任务完成");
        }
    }
    public class DataWrite
    {
        public delegate void UpdateUI(int step);//声明一个更新主线程的委托
        public UpdateUI UpdateUIDelegate;

        public delegate void AccomplishTask();//声明一个在完成任务时通知主线程的委托
        public AccomplishTask TaskCallBack;

        public void Write(object lineCount)
        {
            System.IO.StreamWriter writeIO = new System.IO.StreamWriter("text.txt", false, Encoding.GetEncoding("gb2312"));
           
            for (int i = 0; i < (int)lineCount; i++)
            {
                writeIO.WriteLine(i.ToString() + ",dummy data");
                //写入一条数据,调用更新主线程ui状态的委托
                UpdateUIDelegate(1);
            }
            //任务完成时通知主线程作出相应的处理
            TaskCallBack();
            writeIO.Close();
        }
    }
}

 关键代码

 private void UpdataUIStatus(int step)
        {
            if (InvokeRequired)
            {
                this.Invoke(new AsyncUpdateUI(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();
            }
        }

InvokeRequired用于判断是否是控件所在线程调用的,如果不是的则为true。Invoke用于跨线程调用控件。

更多关于Invoke用法的例子,使用方法本身作为委托。

 private void msg()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(msg));
            }
            else
            {
                textBox2.Text += Environment.NewLine + " >> " + readData;
                MessageBox.Show("hi");
            }
        }

这里MethodInvoker就是一个代理类型

 public delegate void MethodInvoker();

 

总结Invoke的参数,

第一个是委托对象,后面是不定参数。可以写成new object[]{p1,p2...}

 所以,本例程中this.Invoke的代码可以写出

this.Invoke(new AsyncUpdateUI(UpdataUIStatus),new object[]{step});

或者直接

 this.Invoke(new AsyncUpdateUI(UpdataUIStatus),step);

 

posted on 2018-05-23 15:19  legion  阅读(965)  评论(0编辑  收藏  举报

导航