设置文本框线程问题

时间:2011-07-04 11:03:15

标签: c# winforms multithreading textbox

我对C#很陌生,所以如果这是一个有点愚蠢的问题请原谅我。 无论如何,我正在写一个小聊天应用程序,到目前为止似乎进展顺利,我遇到了一个我似乎已修复的问题,但我希望找出为什么我需要这样做。

当我收到消息时,我想更新一个文本框,所以我使用:

txtConnectedID.Text = "test";

但是我收到了这个错误:

System.InvalidOperationException was unhandled by user code
  Message=Cross-thread operation not valid: Control 'txtConnectedID' accessed from a thread other than the thread it was created on.

现在,我认为这与停止运行两次并且无法正确更新的方法有关?我不是百分之百。所以现在我有一个接受字符串的方法的委托,我调用:

private delegate void stringDelegate(string s);

BeginInvoke(new stringDelegate(writeToIPBox), new object[] { e.ConnectedIP.ToString() });

private void writeToIPBox(string newIP)
        {
            txtConnectedID.Text = newIP;
        }

我不知道为什么我这样做,它有什么不同。我不是很高兴在不知道原因的情况下这样做。

提前致谢

4 个答案:

答案 0 :(得分:1)

您应该只尝试从创建它们的线程更新控件。这有很好的理由,因为很容易遇到竞争条件。这些控件不是线程安全的,这是运行时帮助你。

相反,正如您已经想到的那样,您需要在UI线程上更新它,这是BeginInvoke正在做的事情;在UI线程上异步调用委托。

答案 1 :(得分:0)

所有控件都由UI线程(其中只有一个)拥有,并且尝试从另一个线程访问它们会导致此异常。

BeginInvoke在UI线程上调用指定的委托,这就是它工作的原因。您还可以通过选中txtConnectedID.InvokeRequired来检查您是否在UI线程上。

答案 2 :(得分:0)

我花了一分钟坚定的谷歌搜索,但我最终找到了一个“授权”参考:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired%28v=vs.90%29.aspx

简短的回答(从该页面引用)是: Windows窗体中的控件绑定到特定的线程,并且不是线程安全的。

本文还提到如何“内部”处理这个问题...如果control.InvokeRequired(即我们已经从另一个线程调用)在内部处理调用...而不是在整个代码中传播委托

就我个人而言,我从未真正质疑为什么要求代表,我就是这么做的。好问题。

干杯。基思。

答案 3 :(得分:0)

private static void SetText(TextBox tb, string text)
{
    if (tb.InvokeRequired)
    {
        var stDelegate = new StDelegate(SetText);
        tb.Invoke(stDelegate, new object[] { tb, text });
    }
    else
    {
        tb.Text = text;
    }
}