DAY-0429 多线程操作
由于需要使用一个线程来执行对远端设备的实时读取,
1.线程何时启动,目前在每次按下实时读取按钮后创建一个新线程,用于实时读取
2.多线程在关闭再次启动后报错:多线程在每次读取数据按钮click时都需要重新开启,线程的停止使用while中判断isReadPlc还是使用直接Abort,目前未使用Abort,且不用Abort比较安全(不太懂)。
3.跨线程访问报错,方法1:System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; 此方法无法保证线程安全,故更换方案
我们需要使用invoke
首先了解几个概念 同步:调用者需要等待方法调用返回后才能进行下一步工作 异步:调用者可以继续下一步操作,异步方法通常会在另一个线程执行。
阻塞和非阻塞 强调的是程序在等待调用结果(消息,返回值)时的状态. 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 对于同步调用来说,很多时候当前线程还是激活的状态,只是从逻辑上当前函数没有返回而已,即同步等待时什么都不干,白白占用着资源。
private void constantRW_Click(object sender, EventArgs e)//开始多线程读取 { //关闭连线按钮 constantRW.Enabled = false; //打开断线按钮 stop_ConstantRead.Enabled = true; //读取旗标 isReadPlc = true; //创建新线程 threadRead = new Thread(ThreadReadRobot); //将线程设定为后台线程 threadRead.IsBackground = true; //启动该线程,执行方法ThreadReadRobot到最后多线程会在GC中销毁 threadRead.Start(); } private void threadReadFun() { textBox17.Text = textBox17.Text + DELTARobotClient.ReadFloat("1").Content; } private void stop_ConstantRead_Click(object sender, EventArgs e)//停止多线程读取 { //打开连线按钮 constantRW.Enabled = true; //关闭断线按钮 stop_ConstantRead.Enabled = false; //读取旗标 isReadPlc = false; //停止多线程 threadRead?.Abort(); } private void ThreadReadRobot()//多线程读取方法 { while (isReadPlc) { Thread.Sleep(timeSleep); if(isReadPlc) { this.Invoke(new Action(() => { threadReadFun(); })); } } }
实时读取(多线程中的界面更新,需要将涉及界面的代码封装为方法,通过Invoke或者BeginInvoke 调用,减轻UI线程工作量)
多线程1:目前在每次按下实时读取按钮constantRW_Click后创建一个新线程(后台线程),该线程用于实时读取。按下停止按钮stop_ConstantRead_Click后将多线程读取标志位写false,并且关闭线程。
2:添加一个界面更新的代码方法threadReadFun,该方法在后台线程方法ThreadReadRobot中调用,由于是跨线程调用,故使用invoke方式