百度商桥网站代码去哪里添加,快速建设网站视频,手游源码网,怎么做扫码进入网站在使用C#开发winform应用程序时#xff0c;经常会碰到对控件跨线程访问造成的异常。在winform中UI线程和工作线程是分开的#xff0c;但在实际使用中经常会需要在工作线程更新UI线程中创建的控件。 方法1#xff1a;禁用跨线程访问控件检测
.NET默认开启了禁止跨线程控件访…在使用C#开发winform应用程序时经常会碰到对控件跨线程访问造成的异常。在winform中UI线程和工作线程是分开的但在实际使用中经常会需要在工作线程更新UI线程中创建的控件。 方法1禁用跨线程访问控件检测
.NET默认开启了禁止跨线程控件访问在程序中将其置为false取消跨线程访问检测即可实现跨线程访问。
代码中添加如下代码
Control.CheckForIllegalCrossThreadCalls false;
备注该方法虽然可以实现跨线程访问但同时也取消了线程之间冲突访问的检查因此可能会存在多个线程对同一控件进行同时访问此时该控件的值难以预料。因此在实际使用非线程安全不推荐使用
方法2使用delegate和Invoke/BeginInvoke
Invoke是同步的它会等待工作线程完成
BeginInvoke是异步的它会创建另外一个线程去完成工作线程
在使用委托时分为3步委托有C语言中函数指针的意味
定义声明委托---实例化委托---调用委托
1定义声明委托
修饰符 delegate 返回值类型 委托名 ( 参数列表 );
2实例化委托
委托名 委托对象名 new 委托名 ( 方法名 );
委托中的方法民对应的方法的返回值和参数列表的类型和数目必须一致。
3调用委托
委托对象名 ( 参数列表 );
#define USE_DELEGATE
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace SerialPort_CRC8_CRC16
{public partial class Form1 : Form{
#if USE_DELEGATE/* 自定义委托用于实现跨线程对控件的内容更新 */public delegate void MyControlInvoke(Control sender, string data);/// summary/// 更新控件内容/// /summary/// param namecontrol/param/// param namedata/parampublic void UpdataControl(Control control, string data){//判断调用UpdataControl方法的线程和控件线程是否相同不同则需使用Invoke方法相同则直接操作if (control.InvokeRequired true) {MyControlInvoke myControlInvoke new MyControlInvoke(UpdataControl);//方法1异步执行this.BeginInvoke(myControlInvoke, new object[] { control, data }); //方法2同步执行//this.Invoke(myControlInvoke, new object[] { control, data }); }else {control.Text data;}}
#endif/// summary/// Form1类的构造函数/// /summarypublic Form1(){InitializeComponent();serialPort1.DataReceived new System.IO.Ports.SerialDataReceivedEventHandler(serialPort1_DataReceived);cbxPortNum.DataSource System.IO.Ports.SerialPort.GetPortNames();btnOprtPort.BackColor Color.OrangeRed;#if !USE_DELEGATEControl.CheckForIllegalCrossThreadCalls false; //不使用委托时关闭跨线程调用检测非线程安全#endifrbtnCRC16.Checked true;}byte[] myDataByte new byte[] { }; //发送数据缓冲区private void Calculate_CRC16(){CRC16 crc16 new CRC16();string[] myDataStr tBox1.Text.Split( );Listbyte Arc new Listbyte();foreach (var item in myDataStr){try{Arc.Add(Convert.ToByte(item, 16));}catch (Exception){MessageBox.Show(请输入以空格为间隔的16进制字符串);return;}}myDataByte Arc.ToArray();tBox2.Clear();/* 发送该指令至TDM表头读取类别量程信息* 发送xx 03 00 01 00 01 crcL crcH* 接收xx 03 02 class range crcL crcH*/UInt16 crc16Res crc16.Crc16_Modbus(myDataByte, (uint)myDataByte.Length); //计算CRC校验和crc_Data的计算结果为低字节在高位高字节在低位Arc.Add((byte)(crc16Res 8));Arc.Add((byte)(crc16Res));myDataByte Arc.ToArray();sendDataCount Arc.Count;foreach (var item in myDataByte){tBox2.Text (item.ToString(X02) );}}private void Calculate_CRC8(){myCRC mycrc new myCRC();string[] myDataStr tBox1.Text.Split( );Listbyte Arc new Listbyte();foreach (var item in myDataStr){try{Arc.Add(Convert.ToByte(item, 16));}catch (Exception){MessageBox.Show(请输入以空格为间隔的16进制字符串);return;}}myDataByte Arc.ToArray();tBox2.Clear();byte res mycrc.Crc8_init(0x00, myDataByte, (UInt16)(myDataStr.Length));Arc.Add(res);myDataByte Arc.ToArray();sendDataCount Arc.Count;foreach (var item in myDataByte){tBox2.Text (item.ToString(X02) );}}private void button1_Click(object sender, EventArgs e){if (rbtnCRC8.Checked true){Calculate_CRC8();}else if (rbtnCRC16.Checked true){Calculate_CRC16();}}private void btnClear_Click(object sender, EventArgs e){
#if USE_DELEGATEthis.UpdataControl(tBox1, string.Empty);this.UpdataControl(tBox2, string.Empty);this.UpdataControl(tboxSend, string.Empty);this.UpdataControl(tboxRecv, string.Empty);
#elsetBox1.Text string.Empty;tBox2.Text string.Empty;tboxSend.Text string.Empty;tboxRecv.Text string.Empty;
#endif}private void tBox1_KeyDown(object sender, KeyEventArgs e){if (e.KeyCode Keys.Enter){if (rbtnCRC8.Checked true){Calculate_CRC8();}else if (rbtnCRC16.Checked true){Calculate_CRC16();}}}public byte[] usartRecvBuffer new byte[4096]; //开辟4096Byte的接收缓冲区private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e){//if (e.EventType System.IO.Ports.SerialData.Eof)if (serialPort1.BytesToRead 0){return;}string str string.Empty;stopWatch.Stop();TimeSpan timespan stopWatch.Elapsed;str timespan.TotalMilliseconds.ToString() mS;
#if USE_DELEGATEthis.UpdataControl(label6, str);
#elselabel6.Text str;
#endif//串口接收并不是接收的每个字节都会进入该事件因此需在该事件中接收完数据Int32 readByteNum 0;/* 等待数据接收完成即3mS内串口接收到的数据长度不再变化则认为数据已经接收完成 */do{readByteNum serialPort1.BytesToRead;System.Threading.Thread.Sleep(10);} while (readByteNum serialPort1.BytesToRead serialPort1.BytesToRead 4096);serialPort1.Read(usartRecvBuffer, 0, readByteNum); //将串口缓冲区的数据保存至接收缓冲区serialPort1.DiscardInBuffer(); //清空串口缓冲区的内容str string.Empty;for (int i 0; i readByteNum; i){str (usartRecvBuffer[i].ToString(X02) );}
#if USE_DELEGATEthis.UpdataControl(tboxRecv, str);
#elsetboxRecv.Text str;
#endif}public System.Diagnostics.Stopwatch stopWatch new System.Diagnostics.Stopwatch();public int sendDataCount 0; //要发送的字节数/// summary/// “发送”按钮按下/// /summary/// param namesender/param/// param namee/paramprivate void btnSend_Click(object sender, EventArgs e){if (serialPort1.IsOpen false){MessageBox.Show(发送数据前请先打开串口!, 提示);return;}if (sendDataCount 0){MessageBox.Show(发送区为空!, 提示);return;}
#if USE_DELEGATEthis.UpdataControl(label6, 0mS);this.UpdataControl(tboxRecv, string.Empty);this.UpdataControl(tboxSend, tBox2.Text);
#elselabel6.Text 0;tboxRecv.Text string.Empty;tboxSend.Text tBox2.Text;
#endifstopWatch.Restart();serialPort1.Write(myDataByte, 0, sendDataCount); }private void btnOprtPort_Click(object sender, EventArgs e){if (btnOprtPort.Text 单击打开串口){try{//初始化并打开串口serialPort1.PortName cbxPortNum.Text;serialPort1.BaudRate 9600;serialPort1.DataBits 8;serialPort1.Parity System.IO.Ports.Parity.None;serialPort1.StopBits System.IO.Ports.StopBits.One;serialPort1.ReceivedBytesThreshold 1;serialPort1.Open();
#if USE_DELEGATEthis.UpdataControl(label6, 0mS);this.UpdataControl(tboxRecv, string.Empty);this.UpdataControl(tboxSend, tBox2.Text);this.UpdataControl(btnOprtPort, 单击关闭串口);
#elselabel6.Text 0mS;tboxRecv.Text string.Empty;tboxSend.Text tBox2.Text;btnOprtPort.Text 单击关闭串口;
#endifbtnOprtPort.BackColor Color.GreenYellow;}catch (Exception){MessageBox.Show(串口打开失败, 警告);}}else{try{serialPort1.Close();
#if USE_DELEGATEthis.UpdataControl(btnOprtPort, 单击打开串口);
#else btnOprtPort.Text 单击打开串口;
#endifbtnOprtPort.BackColor Color.OrangeRed;}catch (Exception){MessageBox.Show(串口关闭失败, 警告);}}}private void Form1_FormClosing(object sender, FormClosingEventArgs e){if (serialPort1.IsOpen) //程序退出时需关闭已打开串口{try{serialPort1.Close();}catch (Exception){throw;}}}}
}