• Welcome to Valhalla Legends Archive.
 

Modifying GUI elements from multiple threads

Started by TehUser, February 24, 2005, 09:34 AM

Previous topic - Next topic

TehUser

I have an asynchronous socket class that I instantiate in my program.  It has several delegates to handle the various events on the socket.  I add the handlers in my program and attempt to modify GUI elements on the various events.  An error pops up saying that a control may not be modified from another thread (.NET 1 didn't like you doing this, but wouldn't throw an exception).  In searchin the net, there is a lot of talk about using the Invoke method to return control to the GUI thread before updating.  Rather than adding an Invoke for every single piece of GUI I want to update, what is the correct way to notify a GUI thread about an event from an instantiated class?

[MyndFyre edit: I changed the topic title; first I was going to just remove the [.NET 2.0] part, but really I also wanted to make the topic title more clear about what you're dealing with]

dxoigmn


MyndFyre

You can also use the BeginInvoke method on the Control class.  This allows the code performing the action to continue to execute, as the call to BeginInvoke returns immediately, as opposed to the Invoke call, which waits until the GUI thread returns.

For example, in my new bot project, in my common controls library, I have a class that processes chat text and then assigns RTF, control words and all, to the RichTextBox.Rtf property of a rich text box instance.  Here is the code that does it:


#region set rtf code
private delegate void TextCallback(string text);
/// <summary>
/// Sets the rich-text-format text of the chat text box control.
/// </summary>
/// <param name="rtf">The string of RTF, including all control words.</param>
public virtual void SetRtf(string rtf)
{
if (this.Handle == IntPtr.Zero)
{
this.CreateHandle();
}
this.BeginInvoke(new TextCallback(SetTextCallback), new object[] { rtf });
}

private void SetTextCallback(string rtf)
{
m_mutRtf.WaitOne();
if (m_autoScroll)
{
this.rtbChat.Rtf = rtf;
ScrollIntoView();
}
m_mutRtf.ReleaseMutex();

}
#endregion

(full code can be found here).

The SetRtf(string) function, which is public, simply sets up the method to be called.  The delegate passed into BeginInvoke is a function pointer to the SetTextCallback(string) function, which ensures that it is thread safe (the m_mutRtf is a Mutex object on the class) and then assigns the Rtf property of the RichTextBox.

Hth!
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.