子线程与UI线程的通信(委托)

由于项目中存在这样的载入的画面:在界面上有显示载入信息的Label控件和进度条,如果采用单线程则在载入数据的时候UI界面会被锁死,造成假死的感觉。为了给一个更友好的界面,因此有必要引入多线程技术,使得软件更加“人性化”。

但随后在子线程中访问界面上的控件的时候会出现异常,不能操作主线程所控制的UI界面。看来这得用到委托技术了!

首先我们定义委托:

public delegate void loadin(string data, int progress); 

定义委托用delegate关键字,随后跟着一个返回值(这里void就是没有返回值了)loadin是委托名,后面带着两个参数,分别代表显示载入的数据和载入进度条的数值!

在窗体的Load事件里面我们定义一个子线程,用于在后台载入数据并显示载入情况。

定义线程:

ThreadStart ts = new ThreadStart(Downin);  //括号里面的参数是一个方法名,表示线程要处理的方法

     Thread mythread = new Thread(ts);    

 mythread.Start();   //线程开始运作

 

以上三行是线程操作的核心内容,不熟悉线程定义和执行原理等的园友请参考《C#线程参考手册》!

然后我们在Downin方法里面实例化委托并调用之。(这里“实例化”似乎用得不妥,但其实委托和类有很多地方是相似的)

private void Downin()

        {           

            loadin di = new loadin(Update);   //委托后面的参数跟着一个方法名

            this.Invoke(di, "正在初始化系统", 5);    //调用委托所关联的方法,并传递两个参数

            Thread.Sleep(500);                 //线程停止工作0.5

            this.Invoke(di, "正在载入配置信息",35);

            Thread.Sleep(500);

            this.Invoke(di, "正在载入用户数据",70);

            Thread.Sleep(500);

            this.Invoke(di, "正在完成",100);

            Thread.Sleep(500);      

            Thread.CurrentThread.Abort();        //当前线程(子线程)终止          

        }

委托其实就是充当方法的签名,这里委托的参数就是一个方法名,这个方法名带有两个参数,和委托参数表是一样的,同时返回类型也是一样!

private void Update(string data,int progress)     //info标签上显示载入信息

        {

            this.info.Text = data.ToString();

            this.progressBar.Value = progress;

     }

就这样我们绕了一圈,“间接”得通过委托访问主线程构建的控件。

本文只是抛砖引玉,可以了解一下线程和委托的好处。当然,线程并不是越多越好,否则只会增加系统开销,应该看实际需要来应用。

注:如有疏漏之处请指教,谢谢。

原文地址:https://www.cnblogs.com/saper/p/1331062.html