0

尝试从主 MMI 线程以外的其他线程调用文本框时,我碰巧遇到了这个跨线程错误。我已经明白为什么会这样了。我想听听你对我解决这个问题的方式的看法。我使用它是因为我讨厌在代码中添加委托声明。

private void SetText(string text)
{           
    if (textBox1.InvokeRequired)
    {
        this.Invoke(new Action<string>(SetText), new object[]{ text });
    }
    else
    {
        this.textBox1.Text = text;
    }
}

这是正确的方法吗?有没有更好更短的方法?

4

2 回答 2

0

你所拥有的一切都没有错。如果您不想进行递归调用,则可以在Invoke()调用中抛出一个匿名委托:

private void SetText(string text)
{
    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker)delegate
        {
            this.textBox1.Text = text;
        });
    }
    else
    {
        this.textBox1.Text = text;
    }
}
于 2017-06-09T21:37:00.363 回答
0

这是唯一的方法,虽然我会做两个改变:

1)使用 MethodInvoker 以便您可以省略 Func 或 Action 强制转换,但继续使用递归,这样您就不会重复代码。

2)在invoke块中添加一个return,这样你就没有else块了。我宁愿添加一个额外的行而不是额外的缩进。

private void SetText(string text)
{           
    if (textBox1.InvokeRequired)
    {
        this.Invoke((MethodInvoker) delegate { SetText(text); });
        return;
    }

    this.textBox1.Text = text;
}

再想一想,你可以有一个实用方法,它需要一个 Action 来做检查,实际的逻辑总是在 lambda 里面。

private static void InvokeIfRequired(bool required, Action action) {
    // NOTE if there is an interface which contains InvokeRequired 
    //      then use that instead of passing the bool directly.
    //      I just don't remember off the top of my head
    if (required) {
        this.Invoke((MethodInvoker) delegate { action(); });
        return;
    }

    action();
}

private void SetText(string text)
{
    InvokeIfRequired(textBox1.InvokeRequired, () => {
      this.textBox1.Text = text;
    });
}
于 2017-06-10T02:54:53.033 回答