平时在开发过程中,经常会遇到大数据的读取,耗时的操作,这样我们就会用到了多线程。
多线程用起来“真香”!我这里就用到了一个小例子。
需求:我的电脑D:\下有个文件夹documents,这个文件夹里面有许多的文件,我需要将这个些文件的路径获取到,然后添加到一个listBox中,而且每添加一个就停留50ms。这样一个操作,必定会运算很久,这时候我们就会想到用多线程来解决。
打开Visual Studio新建一个winform应用程序,在设计器中添加一个listBox和一个button控件,button控件添加click事件来开启一线程加载文件路径,如图:
程序界面
编写一个线程调用的方法,获取路径并将路径添加到listbox
将文件路径添加到listbox中
在button的click事件写开启新线程
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(AddDataThread);
th.IsBackground = true;//设置为后台线程
th.Start();
}
按下F5调试程序点击button按钮发现抛出异常,如下图:
抛出异常
异常提示:线程间操作无效,我们从不是创建控件"listbox1"的线程中访问它。因为我们在新的线程在向“listbox1”中添加路径,新的线程肯定不是创建"listbox1"的线程,"listbox1"是由主线程创建的,这里就产生了一个跨线程的访问,所以抛出这个异常。
解决这个问题很简单,其实我发现很多的朋友都喜欢这样解决,直接在窗口的Load事件中加上这么一句:
Control.CheckForIllegalCrossThreadCalls = false;
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
现在完美运行了,如图:
运行画面
Control.CheckForIllegalCrossThreadCalls = false; 也就是把检查跨线程访问给关闭了,其实微软MSDN中就有提到过的,这是不安全的做法,我们还有其它的解决办法,也是微软推荐使用的方法,接下来我们把
Control.CheckForIllegalCrossThreadCalls = false;这一行删除。
定义一个委托
Action<string> action;
action = (fileName) => { listBox1.Items.Add(fileName); };
改写一下线程调用的方法
用委托来实现将路径添加到listbox
再次按下F5调试程序,发现运行正常,没有抛出异常
listBox1.InvodeRequired属性返回一个bool值,这个值指示调用方在对控件进行方法调用时是否必须调用Invoke方法,因为调用方位于创建控件所在线程以外的线程中。
在这里直接调用控件对象的Invoke方法用委托很好的解决了跨线程访问的问题。
有喜欢我的文章的朋友,请帮忙转发点赞,谢谢!