替代使用Control.Invoke

时间:2013-07-11 12:08:15

标签: c# .net multithreading visual-studio-2010 visual-studio

在Visual C#/ .Net应用程序中,我必须读取SerialPort,因此我为它分配了一个DataReceivedEventHandler。

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

解决方案似乎是使用Control.Invoke,但是,我有太多的UI动作要执行,所以我担心我可能没有采取正确的路径。

我应该做以下哪项?

  • 选项A:坚持使用调用,并使用Invoke为每个控件执行每个操作的每个操作。

  • 选项B:放置一个50ms的重复计时器,每50ms,我检查一下布尔 DataReceived == true ,如果是,则相应地更新UI控件。 (每次读取串行端口DataReceivedEventHandler中的数据时,DataReceived都设置为true,否则为false。)

  • 选项C:还有其他选择吗?

更新

以下成功(基于@ tcarvin的答案和@Hans Passant的评论)。

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";    
}

2 个答案:

答案 0 :(得分:4)

我认为你在想这个。假设您在表单中编码,这样的事情应该有效。这是嘻嘻哈哈,你可能需要稍微调整一下:

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中。

答案 1 :(得分: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";    
}