Reputation: 3
I have a form that sets up and displays the text box. In the form load method, I am starting a new thread from a completely separate class name Processing
:
private void Form1_Load(object sender, EventArgs e)
{
Processing p = new Processing();
Thread processingThread = new Thread(p.run);
processingThread.Start();
}
Here is the processing class. What I would like to do is create a method in Utilities
class that will allow me to update the text box from whatever class I would need to:
public class Processing
{
public void run()
{
Utilities u = new Utilities();
for (int i = 0; i < 10; i++)
{
u.updateTextBox("i");
}
}
}
Then finally the Utilites
class:
class Utilities
{
public void updateTextBox(String text)
{
//Load up the form that is running to update the text box
//Example:
//Form1.textbox.appendTo("text"):
}
}
I have read about the Invoke
methods, SynchronizationContext
, Background threads and everything else, but almost all examples are using methods in the same class as the Form
thread, and not from separate classes.
Upvotes: 0
Views: 10244
Reputation: 203844
The Progress
class is designed specifically for this.
In your form, before starting the background thread, create a Progress
object:
Progress<string> progress = new Progress<string>(text => textbox.Text += text);
Then provide that progress
object to your worker method:
Processing p = new Processing();
Thread processingThread = new Thread(() => p.run(progress));
processingThread.Start();
Then the processor can report the progress:
public class Processing
{
public void run(IProgress<string> progress)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);//placeholder for real work
progress.Report("i");
}
}
}
The Progress
class, internally, will capture the synchronization context where it was first created and marshall all event handlers invoked as a result of the Report
calls to that context, which is just a fancy way of saying it takes care of moving to the UI thread on your behalf. It also ensures that all of your UI code stays inside the definition of the Form, and all of the non-UI code it outside of the form, helping separate business code from UI code (which is a very good thing).
Upvotes: 3
Reputation: 6983
I would add a AppendText()
method to your Form1 class, like this:
public void AppendText(String text)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<string>(AppendText), new object[] { text });
return;
}
this.Textbox.Text += text;
}
Then from your utility class, call it like this:
class Utilities
{
Form form1; // I assume you set this somewhere
public void UpdateTextBox(String text)
{
form1.AppendText(text);
}
}
There is a very good comprehensive review of threading in .NET that can be found here: Multi-Threading in .NET. It has a section on Threading in WinForms that would help you a lot.
Upvotes: 2