2011-05-10 53 views
12

嗨 我看到下面的代碼:爲什麼在這段代碼中使用Action?

void UpdateMessage (string message) 
{ 
    Action action =() => txtMessage.Text = message; 
    this.Invoke (action); 
} 

爲什麼使用動作,然後在這裏調用操作?爲什麼不使用txtMessage.Text = message來替換函數體中的代碼?


更新

代碼的更全面的版本,在註釋中提出,語法高亮轉載如下,壓痕等

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     new Thread(Work).Start(); 
    } 

    void Work() 
    { 
     Thread.Sleep(5000); 
     UpdateMessage("My Garden"); 
    } 

    void UpdateMessage(string message) { 
     Action action =() => textBox1.Text = message; 
     this.Invoke(action); 
    } 
} 
+0

這是在WinForms的? – 2011-05-10 13:18:04

+1

我認爲你所遇到的是我們在業務中稱爲「壞代碼」的東西。它可能是從實際需要間接尋址的系統中的某個位置複製的。但你是100%正確的。這不是。 – Axeman 2011-05-10 13:19:18

+0

@Axeman如何從提供的代碼中看出UpdateMessage總是在GUI線程中運行? – 2011-05-10 13:22:46

回答

20

因爲這段代碼在不同的線程上運行從用戶界面,必須編組到Invoke與UI線程。

documentationControl.Invoke()狀態:

在擁有此控件的基礎窗口句柄的線程上執行指定的委託。

這是所有必需的,因爲基礎Windows框架要求對窗口句柄的操作由擁有窗口句柄的線程執行。

12

如果UpdateMessage從你需要調用到主線程,以便與GUI元素交互另一個線程調用

如果你只使用txtMessage.Text = message你會得到CrossThreadOperationException

+0

是的,這個UpdateMessage是在主UI線程以外的另一個線程中調用的。但爲什麼我使用txtMessage.Text = message並沒有看到應該在那裏的異常?謝謝! – spspli 2011-05-10 15:07:12

4

你應該在控件的屬性工作UI線程,否則您將收到異常。

Control.Invoke()將通過向窗口消息循環發送窗口消息來執行委託。

但是,當你不需要它,你可以優化代碼,以防止不必要的線程同步功能:在

void UpdateMessage (string message) 
{ 
    if(InvokeRequired) 
    { 
     Invoke((Action)()=>UpdateMessage(message)); 
     return; 
    } 

    txtMessage.Text = message; 
} 
+0

這是完整的代碼: – spspli 2011-05-10 14:24:18

+0

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing;使用System.Linq的 ; using System.Text;使用System.Windows.Forms的 ;使用System.Threading的 ; 命名空間TestAction { \t公共部分Form1類:形式 \t { \t \t公共Form1中() \t \t { \t \t \t的InitializeComponent(); \t \t \t new Thread(Work).Start(); \t \t} \t \t空隙工作() \t \t { \t \t \t Thread.sleep代碼(5000); \t \t \t UpdateMessage(「My Garden」); \t \t} \t \t空隙UpdateMessage(字符串消息) \t \t { \t \t \t行動作用=()=> textBox1.Text =消息; \t \t \t this.Invoke(action); \t \t} \t} } – spspli 2011-05-10 14:24:33

+1

在此代碼中,您可以從構造函數中啓動的線程中調用UpdateMessage方法。 Control.Invoke()調用在當前場景中是必需的。 – 2011-05-10 14:33:18