2015-12-03 71 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

我試圖幫忙。它不是聲譽... –

相關問題