使用C#的MethodInvoker.Invoke()方法来编写GUI应用程序...这样做好吗?

28

我使用 C# 2.0 和 MethodInvoker 委托,我的 GUI 应用程序从 GUI 线程或工作线程接收一些事件。

我使用以下模式来处理表单中的事件:

private void SomeEventHandler(object sender, EventArgs e)
{
    MethodInvoker method = delegate
        {
            uiSomeTextBox.Text = "some text";
        };

    if (InvokeRequired)
        BeginInvoke(method);
    else
        method.Invoke();
}

使用这种模式,我不会复制实际的UI代码,但我不确定这种方法是否好。

特别是,这一行:

method.Invoke()

它是使用另一个线程进行调用还是在GUI线程上直接调用该方法?

5个回答

23
method.Invoke() 调用会在当前执行线程上执行委托。使用 BeginInvoke(method) 确保委托在 GUI 线程上被调用。
当相同方法可以从 GUI 线程和其他线程调用时,这是避免代码重复的正确方法。

谢谢!我之前在使用method.Invoke和Invoke((MethodInvoker)时遇到了困难。回到BeginInvoke就解决了问题。 - Tony D

15

个人而言,我喜欢这种方法:

private void ExecuteSecure(Action a)
{
    if (InvokeRequired)
        BeginInvoke(a);
    else
        a();
}

然后你可以写出像这样的一行代码:

ExecuteSecure(() => this.Enabled = true);

这里似乎有些不对劲。InvokeRequired是在控件上操作的,你只是把它放在那里而已。这是什么意思? - Craig
1
InvokeRequired和this.InvokeRequired是相同的。 - bluekushal

5
请记住,如果您在后台线程上且Control.IsHandleCreated为false,则Control.InvokeRequired将返回false。我建议使用Debug.Assert来保护代码,检查是否已创建未托管的句柄。

2

对于WinForms,调用Control.Invoke(Delegate)会向UI线程的消息泵发送一条消息。然后线程处理该消息并调用委托。一旦处理完毕,Invoke停止阻塞,调用线程继续运行您的代码。


0

它在同一线程上进行调用。您可以通过逐步执行代码来检查。这种方法没有任何问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接