一、背景
由于在窗体程序中通过点击一个button
按键后需要更新TreeView
控件的内容,由于等待时间比较长,主程序无法一起在那边等待,需要去处理其它的事情,所以就需要创建新的子线程来处理。因为主线程主要用于窗体程序的更新,但子线程又存在问题是C#中禁止跨线程直接访问控件
,所以子线程中要更新窗体程序的控件要使用委托主线程来处理更新控件。
二、程序分析
using System.Threading; //声明线程命名空间
private void Updatebutton_Click(object sender, EventArgs e) //按键控件处理程序
{
Thread SearchDevice = new Thread(FindCanDevice); //子线程的创建
if (update_flag ==false) //开始更新网络设备
{
update_flag =true;
UpdateprogressBar.Maximum= 127; //总共会查询126个设备
DevicetreeView.Nodes.Clear(); //快速清空TreeView的内容
NodeList = new TreeNode("Device List", 0, 0);
this.DevicetreeView.Nodes.Add(NodeList); //加入根节点
//Thread SearchDevice = new Thread(FindCanDevice);
SearchDevice.IsBackground = true; //当主线程关闭时,子线程也随着关闭
SearchDevice.Start(); //子线程启动
}
else //停止更新网络设备
{
update_flag = false;
}
}
private void FindCanDevice() //子线程处理程序
{
int ret; //寻找设备的状态
int countnum = 0;
for (int j = 1; j < 128; j++)
{
if (!update_flag) //退出网络设备的更新
break;
countnum++;
ret = GloableVar.WzCanOpenUpdateNetwork(j);
ShowDevice(ret, j, countnum);
}
}
public delegate void aa(int flagSuccess, int data, int count); //委托类型的说明
private void ShowDevice(int flagSuccess, int data, int count)
{
if(this.InvokeRequired) //判断是不是控件所在线程调用的,不是的话为true,Invoke用于跨线程调用控件进行操作
{
aa a = new aa(ShowDevice); //定义委托的函数
this.Invoke(a, new object[] { flagSuccess, data, count }); //指定用主线程中的控件去调用这个委托,相当于主线程来执行这个函数
}
else
{
if(flagSuccess== 0)
{
TreeNode NodeDevice = new TreeNode("Node ID " + data.ToString());
NodeList.Nodes.Add(NodeDevice); //加入子节点
DevicetreeView.ExpandAll(); //展开所有的节点
}
UpdateprogressBar.Value = count;
}
}
1、 Thread SearchDevice = new Thread(FindCanDevice)
为新建的子线程,子线程的处理函数为void FindCanDevice()
,完成线程创建后需要启动线程 SearchDevice.Start()
,线程才会运行。
2、在进入子线程处理函数后,如果因为控件是主线程创建的,子线程不是控件所在的线程调用,所以this.InvokeRequired
一直为true
,进入判断程序后通过this.Invoke
将子线程的处理委托给主线程去处理,由于委托的函数为ShowDevice
并且当前调用执行的线程为控件所在的主线程调用,这时又判断this.InvokeRequired
为false
,所以执行控件的更新处理
if(flagSuccess== 0)
{
TreeNode NodeDevice = new TreeNode("Node ID " + data.ToString());
NodeList.Nodes.Add(NodeDevice); //加入子节点
DevicetreeView.ExpandAll(); //展开所有的节点
}
UpdateprogressBar.Value = count;
三、参考文档
http://www.cnblogs.com/miniwiki/archive/2010/06/18/1760540.html //线程的创建
http://www.cnblogs.com/songxingzhu/p/3677307.html //InvokeRequired和Invoke的使用
by 羊羊得亿
2017-07-04 ShenZhen