2015-12-03 44 views
4

我偶然发现了专业库中的一些代码,并且不确定这是否是处理跨线程事件调用的干净方式。线程安全事件 - 这是一种“干净”的方式吗?

以下代码位于表单应用程序中。线程调用是从一个类本身开始一个新的线程和接收消息:

private void Library_StatusChanged(object sender, AbstractTestCase.StatusChangedEventArgs e) 
{ 
    if (this.InvokeRequired) 
    { 
     this.lblProgress.Invoke((MethodInvoker)delegate() 
     { 
      lblProgress.Text = "Current state: " + e.Step; 
      lblProgress.Refresh(); 
     } 
     ); 

     this.pbProgess.Invoke((MethodInvoker)delegate() 
     { 
      pbProgess.Value = e.Percentage; 
      pbProgess.Refresh(); 
     }); 

     this.lstStatus.Invoke((MethodInvoker)delegate() 
     { 
      lstStatus.Items.Add(" " + e.Step); 
      lstStatus.Refresh(); 

     }); 

     this.Invoke((MethodInvoker)delegate() 
     { 
      this.Refresh(); 
     }); 
    } 
    else 
    { 
     lblProgress.Text = "Current state:" + e.Step; 
     lblProgress.Refresh(); 

     pbProgess.Value = e.Percentage; 
     pbProgess.Refresh(); 

     lstStatus.Items.Add(" " + e.Step); 
     lstStatus.Refresh(); 

     this.Refresh(); 
    } 

    Application.DoEvents(); 
} 

这是“最先进的”?在我看来这有点凌乱?!

+0

我通常使用Application.DoEvents'的'作为符号的东西是不正确的。只需要一个'Invoke'而不是4个单独的''''''可能会更有效率。 –

+0

库是单线程的(除了一些罕见的多线程部分),因此UI冻结。 – AllDayPiano

+1

*“因此UI冻结”*和'Application.DoEvents'是一个非常糟糕的方式来解决这个问题。 –

回答

5

技术现状是使用await。如果这在这里是不可能的,至少简化代码到一个单一的Invoke调用。无需在每个控件上调用,只需调用UI线程上的任何位置即可。

InvokeRequired检查不应该被要求,因为你应该知道什么线程的事件引发。

在任何情况下,重复逻辑如"Current state: " + e.Step真的是一个坏主意,无论如何我都会在代码审查中失败。

Application.DoEvents的存在是一个非常糟糕的迹象。可能是一个误解,因为它只在UI线程上调用它是有道理的,但为什么Invoke已经在UI线程上?!看起来像是一个矛盾。

lstStatus.Refresh();也是一种误解,可能是迷信。控件自动刷新(如果您允许进行事件处理)。

+0

嗨,回答你的问题:这个调用是必需的,因为这个事件可能没有被同一个线程触发。有一些像在另一个线程中运行的异步com端口访问。它也可能发生,UI线程完全忙碌,因此DoEvent可能会重新绘制表单?! Control.Refresh() – AllDayPiano

+1

*'lstStatus.Refresh();'也是一种误解,可能是迷信。*货物崇拜节目。 –

+0

@MattBurland是的,这个人做了一次,它隐藏了UI线程冻结,所以他现在永远认为这是解决方案。 – usr

1

当您使用invoke时,将在队列中添加一条语句以供UI线程处理。

使用这个简单的解决方案:

private void Library_StatusChanged(object sender, AbstractTestCase.StatusChangedEventArgs e) 
{ 
    this.lblProgress.Invoke((MethodInvoker)delegate() 
    { 
     lblProgress.Text = "Current state: " + e.Step; 
    }); 

    this.pbProgess.Invoke((MethodInvoker)delegate() 
    { 
     pbProgess.Value = e.Percentage; 
    }); 

    this.lstStatus.Invoke((MethodInvoker)delegate() 
    { 
     lstStatus.Items.Add(" " + e.Step); 
    }); 
} 
+1

这不是OP代码。它来自图书馆。我假设他们不打算重新编写图书馆。他们只是在问他们遇到的代码。 –

+0

Jup Matt,你是对的。我不喜欢lib,但免费是便宜,便宜好,好接近完美,完美是,预期: -/ – AllDayPiano

+0

我试图帮忙。它不是声誉... –

相关问题