invoke委托解决“线程间操作无效: 从不是创建控件的线程访问它”的问题
来源:互联网 发布:紫胤真人知乎 编辑:程序博客网 时间:2024/05/14 19:14
1.问题描述
在线程中更改控件属性时,编译器报错:“线程间操作无效: 从不是创建控件的线程访问它”。查看资料后得知这个问题的根本在于,创建新线程后,新线程跟主线程同步运行,这时如果新线程提出对控件进行修改,将被编译器报错,因为可能会出现主线程跟新线程同时对同一控件进行修改的情况,这样就造成了程序执行的混乱。C#委托可以合理解决这一问题。取用委托后,被委托代码的执行顺序将被改变以避免冲突,具体原理请自行查阅。C#提供两种委托方法,一个是invoke,另一个是BeginInvoke。关于这两个的区别请自行查阅,在此只介绍BeginInvoke方法。
2.解决方法
1.使用delegate声明委托 public delegate void MyInvoke(byte[] receiveBytes);'
MyInvoke为委托名,()里面为要传给代理函数的值。
2.新写一个代理函数,来调用执行对控件的操作。
在线程里面加入委托来调用代理函数刷新控件。
3.实例
因为此项目较大,所以只摘出能表示出此问题的部分。在此,将删减无关代码以增加代码简洁度,所以不保证贴出阉割版代码能够运行。
未加委托之前的错误代码:
public mainForm() { // // Windows 窗体设计器支持所必需的 // InitializeComponent(); // // TODO: 在 InitializeComponent 调用后添加任何构造函数代码 // } /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.Run(new mainForm()); } Boolean flagLed1 = false; Boolean flagLed2 = false; Boolean flagTiltA = false; Boolean flagTiltB = false; Boolean flagManipA = false; Boolean flagManipB = false; Boolean flagThruster = false; private void mainForm_Load(object sender, EventArgs e) { } UdpClient udpClient = null; Thread thread; private void BUTTudpConnect_Click(object sender, EventArgs e) { if (BUTTudpConnect.Text == "connect") { udpClient = new UdpClient(Convert.ToInt32(TBLocalPort.Text)); try { udpClient.Connect(TBRemoteIP.Text, Convert.ToInt32(TBRemotePort.Text)); UdpSend( udpClient); thread = new Thread(UdpListing); //这里新建了线程去持续监听UDP端口。 thread.Start(udpClient); thread.IsBackground = true; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } BUTTudpConnect.Text = "disconnect"; } else { thread.Abort(); BUTTudpConnect.Text = "connect"; udpClient.Close(); } } private void UdpListing(Object obj) { UdpClient udpClient; udpClient = (UdpClient)obj; //IPEndPoint object will allow us to read datagrams sent from any source. IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); while(true) { Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); string returnData = Encoding.ASCII.GetString(receiveBytes); labelDHeading.Text = returnData.ToString(); //错误,在线程里更改了主线程窗体里的控件属性。 } }
修改了三处地方,并在修改的地方标注了序号。如下
修改后的代码:
public mainForm() { // // Windows 窗体设计器支持所必需的 // InitializeComponent(); // // TODO: 在 InitializeComponent 调用后添加任何构造函数代码 // } /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.Run(new mainForm()); } Boolean flagLed1 = false; Boolean flagLed2 = false; Boolean flagTiltA = false; Boolean flagTiltB = false; Boolean flagManipA = false; Boolean flagManipB = false; Boolean flagThruster = false; //更改处1/3 声明委托 public delegate void MyInvoke(byte[] receiveBytes); private void mainForm_Load(object sender, EventArgs e) { } UdpClient udpClient = null; Thread thread; private void BUTTudpConnect_Click(object sender, EventArgs e) { if (BUTTudpConnect.Text == "connect") { udpClient = new UdpClient(Convert.ToInt32(TBLocalPort.Text)); try { udpClient.Connect(TBRemoteIP.Text, Convert.ToInt32(TBRemotePort.Text)); UdpSend( udpClient); thread = new Thread(UdpListing); thread.Start(udpClient); //这里新建了线程去持续监听UDP端口。 thread.IsBackground = true; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } BUTTudpConnect.Text = "disconnect"; } else { thread.Abort(); BUTTudpConnect.Text = "connect"; udpClient.Close(); } } //更改出2/3 将更改控件的代码更改为代理函数以方便委托。 private void UpdateControls(byte[] receiveBytes) { string returnData = Encoding.ASCII.GetString(receiveBytes); labelDHeading.Text = returnData.ToString(); } private void UdpListing(Object obj) { UdpClient udpClient; udpClient = (UdpClient)obj; //IPEndPoint object will allow us to read datagrams sent from any source. IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); while(true) { Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); MyInvoke mi = new MyInvoke(UpdateControls); //更改出3/3 委托 this.BeginInvoke(mi, new Object[] { receiveBytes }); } }
阅读全文
0 0
- invoke委托解决“线程间操作无效: 从不是创建控件的线程访问它”的问题
- 线程间操作无效: 从不是创建控件“**”的线程访问它 利用委托处理
- 线程间操作无效:从不是创建控件 的线程访问它 使用委托
- 后台线程与UI线程问题:解决“线程间操作无效: 从不是创建控件xxx的线程访问它”
- WinForm中线程问题:线程间操作无效: 从不是创建控件“...”的线程访问它
- c#线程问题:线程间操作无效:从不是创建控件 的线程访问它
- WinForm中线程问题:线程间操作无效: 从不是创建控件“...”的线程访问它
- WinForm解决多线程操作控件问题 线程间操作无效: 从不是创建控件的线程访问它"
- 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- BackGroundWorker解决“线程间操作无效: 从不是创建控件的线程访问它”
- BackGroundWorker解决 线程间操作无效: 从不是创建控件的线程访问它
- 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- 如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- 经典解决“线程间操作无效: 从不是创建控件的线程访问它”
- 解决"线程间操作无效: 从不是创建控件的线程访问它"
- 解决 线程间操作无效: 从不是创建控件的线程访问它
- BackGroundWorker解决“线程间操作无效: 从不是创建控件的线程访问它” (C# VS2008)
- 什么是概率?对我有什么用?
- activiti学习--07流程历史数据
- 第11章 曲线积分与曲面积分
- 标签转化
- ios 触摸事件 学习
- invoke委托解决“线程间操作无效: 从不是创建控件的线程访问它”的问题
- 《ECMAScript 6 入门优化版》
- Java十四种开发工具及其特点
- WPF循环显示图片解决OutofMemoryException方法
- SGISTL源码探究-第一级配置器
- XHTML 相对路径与绝对路径
- hive基础操作
- HDU
- bzoj 3390: [Usaco2004 Dec]Bad Cowtractors牛的报复