C# CrossThreadMessaging 读取标签文本

C# CrossThreadMessaging on reading label text

我看过无数主题,但他们都在谈论更新控件的 text 而不是 检索它的值。

我目前使用以下函数来避免 cross thread operations 并且在调用函数或赋值时工作正常。

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

那么,什么有效

ExecuteSecure(() => this.label_options.Text = "Hello");

你需要什么?

string value = string.Empty;
ExecuteSecure(() => value = this.label_options.Text);

创建一个像 ExecuteSecure() 一样工作的默认函数会很棒。

你有什么错误?

Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException

当我将光标移动到 this.label_options.Text 值时出现此消息。

编辑 1: 下面的图像显示了错误,尽管代码有效。

最简单的解决方法是改用 Invoke()。它是同步的(在调用方法 return 之前不会 return),因此您可以依靠它来设置捕获的变量状态。

其中一个版本是简单地修改您现有的方法以调用 Invoke() 而不是 BeginInvoke()。另一种方法是制作一个通用方法,该方法实际上 returns 传入的值 Func<T> returns:

private T getExecuteSecure<T>(Func<T> f)
{
    if (InvokeRequired)
        return (T)Invoke(f);
    else
        return f();
}

你可以这样使用它:

string value = getExecuteSecure(() => this.label_options.Text);

注意和上面类似,在使用BeginInvoke()时也可以收到return值。但这很棘手,因为您只能从对 EndInvoke() 的调用中获取它,在您知道调用的委托已完成后执行(这反过来又可以通过 IAsyncResult returned 找到来自 BeginInvoke()).


编辑:

至于你在调试器中看到的异常,这是因为当 VS 计算一个 属性 时,它实际上在一个线程中运行 属性 getter。但是该线程不是 属性 的正确线程。因此例外。