27

使用 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 线程上的方法的直接调用?

4

5 回答 5

22

method.Invoke()调用在当前执行线程上执行委托。使用BeginInvoke(method)确保在 GUI 线程上调用委托。

当可以从 GUI 线程和其他线程调用相同的方法时,这是避免代码重复的正确方法。

于 2009-04-23T15:33:27.627 回答
15

我个人喜欢这种方法:

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

然后你可以像这样编写单行代码:

ExecuteSecure(() => this.Enabled = true);
于 2011-11-05T15:06:42.340 回答
5

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

于 2009-04-28T18:01:03.753 回答
2

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

于 2009-04-23T15:37:19.413 回答
0

它在同一个线程上进行调用。您可以通过单步执行代码来检查。这种方法没有错。

于 2009-04-23T15:32:28.317 回答