C#CrossThreadMessaging读取标签文本

时间:2015-03-10 16:44:01

标签: c# thread-safety

我看过无数主题,但所有主题都谈到更新控件的<{1}}值而不是检索它的值。

我目前使用以下函数来避免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); 一样的默认函数会很棒。

你有什么错误

  

Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException

当我将光标移动到ExecuteSecure() .Text的值时,会显示此消息。

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

1 个答案:

答案 0 :(得分:0)

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

其中一个版本就是简单地修改现有方法,以便调用Invoke()而不是BeginInvoke()。另一种方法是创建一个实际返回传入的Func<T>返回的值的泛型方法:

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

你可以这样使用:

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

请注意,与上面类似,使用BeginInvoke()时也可以接收返回值。但这很棘手,因为你只能通过调用EndInvoke()来获取它,在你知道调用的委托已经完成后执行(反过来你通过从{{1}返回的IAsyncResult找到了})。


修改

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