我正在尝试创建一个类似超级终端的程序,但我无法获得串行端口以获取一行并将其发布到后台的列表框中。在下面的例子中,它将冻结整个程序,而for循环运行100次,然后吐出所有100行......我希望它逐行更新,我不知道它为什么这样做。
我也试过背景工作者,但似乎做了同样的事情。
提前致谢...
static System.Threading.Thread thread;
public void button2_Click(object sender, RoutedEventArgs e)
{
if(Sp.IsOpen){
stop = false;
thread = new System.Threading.Thread(
new System.Threading.ThreadStart(
delegate()
{
System.Windows.Threading.DispatcherOperation
dispatcherOp = listBox1.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
for(int y = 0; y <100; y++)
{
String line = Sp.ReadLine();
listBox1.Items.Add(line);
}
}
));
}
));
thread.Start();
}else{
item.Content = ("No Comm Ports are Open");
item.IsSelected = true;
listBox1.Items.Add(item);
}
}
答案 0 :(得分:1)
您正在UI线程中运行SP.ReadLine
代码。
我已将您的代码拆分为三种方法,而不是一大堆代码。
private Thread _thread;
private void Kickoff()
{
_thread = new Thread(() => ScheduleWork(listBox1));
thread.Start();
}
private void ScheduleWork(ListBox box)
{
box.Dispatcher.BeginInvoke((Action)() => Fill(box));
}
private void Fill(ListBox box)
{
for(int y = 0; y <100; y++)
{
String line = Sp.ReadLine();
listBox1.Items.Add(line);
}
}
在这个澄清版本中,有三种方法
_thread
上运行并计划填写_thread
上运行的工作问题是 Kickoff 在UI线程上运行, ScheduleWork 在_thread
上运行,而 Fill 在UI上运行线。
Dispatcher.BeginInvoke本质上意味着“采用这种方法,并在你想要安排它时,在UI线程上运行它,kthxbai。”所以你的代码都在UI线程上运行。
您需要执行以下操作
private Thread _thread;
private void Kickoff()
{
_thread = new Thread(() => ScheduleWork(listBox1));
thread.Start();
}
private void ScheduleWork(ListBox box)
{
for(int y = 0; y <100; y++)
{
String line = Sp.ReadLine();
box.Dispatcher.BeginInvoke((Action<string>)(str) =>
listBox1.Items.Add(str),
line);
}
}
答案 1 :(得分:0)
我认为正在发生的事情是你的线程优先于GUI线程。您必须睡眠线程,以便GUI可以更新,或者它只会排队一堆更新,然后在事件结束且程序空闲时处理该队列。将它设置为较低的优先级可能不是一个很好的方法。
就个人而言,我会将COM端口逻辑移动到一个对象中,并将其工作在自己的线程上。然后,您可以在计时器上轮询该对象的属性,以查看是否有任何数据可供读取。
答案 2 :(得分:0)
您无法从后台线程更新UI。尝试将此行更改为
listBox1.Dispatcher.BeginInvoke(DispatcherPriority.Render, ()=>listBox1.Items.Add(line));
尝试使用MSDN: DispatcherPriority来改变线程的优先级。