2013-07-11 40 views
1

在Visual C#/ .Net应用程序中,我必须读取SerialPort,因此我将其分配给DataReceivedEventHandler。替代使用Control.Invoke

但是,我当然不能直接从处理程序中更改UI控件,因为它们位于单独的线程中。

该解决方案似乎是使用Control.Invoke,但是,我有太多的UI操作来执行,所以我担心也许我没有走正确的道路。

我应该做以下哪一项?

  • 选项A:与调用坚持无论如何,并且执行每个上的每个使用调用为每个的各种控制的动作。选项B:放置一个50ms重复计时器,其中每50ms检查一次布尔值是否为DataReceived == true,如果是,则相应地更新UI控件。 (每次我读取串行端口DataReceivedEventHandler中的数据时DataReceived设置为true,否则为false)。

  • 选项C:任何其他选项?

UPDATE:

成功具有以下(根据@ tcarvin答案,并@Hans帕桑特的评论)。

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (this.InvokeRequired()) 
    { 
     this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(DataReceivedHandler), new object[] { sender, e }); 
     return; 
    } 

    tbSerialStatus.Text = "Received text";  
} 
+1

只需努力缓冲您收到的数据。经常调用没有太大意义,你只需要保持人眼快乐。无论如何,做这件事通常都是有问题的,它会导致UI线程获取太多调用请求并停止绘画的问题。 –

回答

3

我想你已经在想这个了。假设你在一个表单中编码,这样的事情应该工作。这是从臀部,你可能需要调整它一点:

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 

    if (this.InvokeRequired) 
    { 
     this.Invoke(new EventHandler<SerialDataReceivedEventArgs>(DataReceivedHandler), sender, e); 
     return; 
    } 

    // everything here runs on the UI thread, do what you like, 
    // and update as many UI controls as you like. 

} 

正如你所看到的,你不必包装在一个单独的Control.Invoke每个控制访问。

+0

啊,所以每个控件不需要单独调用!但为什么它是'Control.Invoke',不应该是'this.Invoke'?另外,为什么你将'DataReceivedHandler'指定为委托 - 我们已经在该处理程序中,所以不应该改为在UI线程上使用方法?我知道你只是写了这个草案,但我试图确定。 – boardbite

+0

这是一个麻烦的答案。不要像那样使用Control.BeginInvoke。它是一种财产,而不是一种方法,它总是会成为真实的。 *永远不会*使用Control.Invoke(),它是死锁的主要来源。特别是在DataReceived事件处理程序中,在程序退出时在UI线程上调用SerialPort.Close()方法对死锁具有很高的可能性。始终使用BeginInvoke()代替。 –

+0

问题解决了 - 谢谢你们俩! (请参阅我的问题上的工作代码UPDATE。) – boardbite

0

已解决。此方法的工作原理如下:

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (this.InvokeRequired()) 
    { 
     this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(DataReceivedHandler), new object[] { sender, e }); 
     return; 
    } 

    tbSerialStatus.Text = "Received text";  
}