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