现在有个WPF的界面WINDOW,里面有tabcontrolA和B和C,A的tabitem3里面套着B,B的tabitetm1里面套着C。
A/B/C分别都有各自的selectionchanged事件,每个事件中都有各自的向串口发送数据并等待接收返回信号的代码。
在选择A的tabitem3时,会按A-B-C的顺序触发各自的selectionchanged事件,然后同时呢会有UI界面的改变(显示A的tabitem3里面的界面)。原因是首先要等待返回信号,所以为了防止界面的假死,在等待函数中用了system.windows.forms.application.doevents()方法。
(PS:原因是项目以前是用的WINFORM,WINFORM的机制和显示顺序跟WPF的不一样,所以同样的思路在winform上没问题,现在项目要改成WPF的,就出现了问题。但是本人也没找到WPF上对应的doevents方法,网上查的有人说可以直接用forms的就直接用了)
问题呢就在于,A的selectionchanged事件完成了,在B的selectionchanged事件时原因是和UI更新同时了,所以导致doevents()提示了“调度程序进程已挂起,但消息仍在处理中。”的错误信息(本人猜的这个原因,假如不对,还请大家指正)。
假如本人打断点从B的selectionchanged事件中发送消息开始逐语句调试,就没任何问题。假如是逐过程就会产生同样的问题。
请大家帮帮忙,看看这应该怎么改一下?
A/B/C分别都有各自的selectionchanged事件,每个事件中都有各自的向串口发送数据并等待接收返回信号的代码。
在选择A的tabitem3时,会按A-B-C的顺序触发各自的selectionchanged事件,然后同时呢会有UI界面的改变(显示A的tabitem3里面的界面)。原因是首先要等待返回信号,所以为了防止界面的假死,在等待函数中用了system.windows.forms.application.doevents()方法。
(PS:原因是项目以前是用的WINFORM,WINFORM的机制和显示顺序跟WPF的不一样,所以同样的思路在winform上没问题,现在项目要改成WPF的,就出现了问题。但是本人也没找到WPF上对应的doevents方法,网上查的有人说可以直接用forms的就直接用了)
问题呢就在于,A的selectionchanged事件完成了,在B的selectionchanged事件时原因是和UI更新同时了,所以导致doevents()提示了“调度程序进程已挂起,但消息仍在处理中。”的错误信息(本人猜的这个原因,假如不对,还请大家指正)。
假如本人打断点从B的selectionchanged事件中发送消息开始逐语句调试,就没任何问题。假如是逐过程就会产生同样的问题。
请大家帮帮忙,看看这应该怎么改一下?
解决方案
20
20
版主说的对,串口通信用异步回调,或用子线程,等到结果后切换到主线程。
(用BackgroupWorker吧,wpf和winform都是一样的,在proccessChanged事件中更新主线程即可,按照事件先后顺序,并不会有冲突)
10
// This event handler is where the time-consuming work is done. private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; for (int i = 1; i <= 10; i++) { if (worker.CancellationPending == true) { e.Cancel = true; break; } else { // Perform a time consuming operation and report progress. System.Threading.Thread.Sleep(500); //此处,死循环不断执行读串口,获取数据,然后随便报进度,有数据就报进度,随便百分比进度就行了 worker.ReportProgress(i * 10);//有数据就通知主线程 } } } // This event handler updates the progress. //主线程操作数据结果,每次报告进度都会执行这个ProgressChanged private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { resultLabel.Text = (e.ProgressPercentage.ToString() + "%"); } // This event handler deals with the results of the background operation. //整个backgroundWorker结束后才会执行一次RunWorkerCompleted。 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled == true) { resultLabel.Text = "Canceled!"; } else if (e.Error != null) { resultLabel.Text = "Error: " + e.Error.Message; } else { resultLabel.Text = "Done!"; } }
所以在dowork里面,多次执行worker.ReportProgress(随便一个1-100的数字都可以);就会不断处理串口的数据