Thread-safe updates of a WinForm control from other classes
Solution 1
delegate
can be used for Thread safe calls
Check this http://msdn.microsoft.com/en-us/library/ms171728.aspx
// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void SetTextCallback(string text);
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
Solution 2
Typically you should run this kind of time-consuming operations in a BackgroundWorker
. Define a work method:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// execute your WriteOutput method
}
and set is as the DoWork
event handler:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync(); // start the worker
To safely update the UI from a different thread use the Control.BeginInvoke
method:
mainForm.BeginInvoke(
() => { mainForm.UpdateLog(<text>); });
Solution 3
As suggested by Sonu, delegate
can be used for Thread safe calls, and you can use Linq to shorten the code:
this.BeginInvoke( (Action) delegate ()
{
//code to update UI
});
See this link for more information.
Luke G
Updated on June 18, 2022Comments
-
Luke G almost 2 years
Could someone please help me with the following problem:
There are two classes MainForm and LWriter. Below is a method from the LWriter that in addition to writing to a file sends some updates to a RichTextBox control (through mainForm.UpdateLog(text)). Everything works fine, however, this WriteOutput method also does some extensive processing that during the calculation freezes the form.
I think the WriteOutput should be encapsulated in a separate thread. Could someone please help me out explaining how to place WriteOutput (LWriter class) in a thread that will then call mainForm.UpdateLog() from the mainFrom in a safe manner?
I am new to threads, thus help would be much appreciated.
public void WriteOutput(string output, Links[] links) { try { using (StreamWriter sw = new StreamWriter(output)) { for (int x= 1; x<links.Length;x++) { ... sw.WriteLine( ... ); sw.Flush(); } mainForm.UpdateLog(<text>); } } catch(Exception e) { ... } }
-
AH. about 9 yearsBy far the most elegant solution. Thanks.