开发者

Setting text boxes thread issues

I'm pretty new at C# so forgive me if this is a bit of a silly question. Anyway I'm writing a little chat application that so far seems to be going well, I've run into a problem that I seem to have fixed but I'm hoping to work out why I need to do it this way.

When I receive a message I want to update a text box so I use:

txtConnectedID.Text = "test";

But I receive this error:

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.

Now, I think this has something to do with stopping the method running twice and not updating properly? I'm not 100% on this. So now I have a delegate for a method that accepts a string and I call:

private delegate void stringDelegate(string s);

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

private void writeToIPBox(string newIP)
        {
            txtConnectedID.Text = newIP;
       开发者_Python百科 }

I'm not sure why I'm doing this, how it's any different. I'm not really happy to just do it this way without knowing why.

Thanks in advance


You should only attempt to update controls from the thread on which they were created. There are good reasons for this as it is easy to hit a race condition. These controls are not thread safe and this is the runtime helping you out a bit.

Instead, as you have figured out, you need to update it on the UI thread, which is what BeginInvoke is doing; calling the delegate asynchronously on the UI thread.


All controls are owned by the UI thread (of which there is only one), and trying to access them from another thread results in this Exception.

BeginInvoke calls the specified delegate on the UI thread, which is why it works. You can also check if you are on the UI thread by checking txtConnectedID.InvokeRequired.


It took a new minutes of determined googling but I eventually found an "authorative" reference:

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

The short answer (to quote from that page) is: Controls in Windows Forms are bound to a specific thread and are not thread safe.

This article also aludes to how this can be handled "internally"... if control.InvokeRequired (i.e. we've been called from another thread) handle the invocation internally... rather than spreading delegates throughout your code.

Personally I'd never really questioned WHY a delegate was required, I just did it. Good question.

Cheers. Keith.


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;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜