现在有个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的数字都可以);就会不断处理串口的数据