I have my main GUI from where I start a long running method in a separate thread. Now from within this separate thread I need to create and show a new form. But when I show
Put the code that creates the new GUI into the main GUI class and then call the main GUI's Invoke method, or raise an event that the main GUI can subscribe to to know when to trigger the new GUI. If you choose the latter, be sure to use InvokeRequired to determine if you can call the method that creates the new GUI directly or if you need to use an Invoke to get back onto the GUI thread to create the new GUI.
Use Form.Show instead of Form.ShowDialog. You can also use a BackgroundWorker to do concurrent tasks.
You need to learn about Control.BeginInvoke/Invoke and all that means. Just remember that all UI operations need to occur on the main thread (UI thread) because that is the thread that owns the message pump. You need to call back into that thread in order to have UI actions happen.
Here's an intro to the BeginInvoke/Invoke stuff: http://weblogs.asp.net/justin_rogers/pages/126345.aspx
In order to help further here's a complete working code example that should highlight the basics.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var worker = new Worker(this);
worker.Start();
}
public void updateLabel(int value)
{
if(label1.InvokeRequired) { // check if on UI thread
//If true use begin invoke to call update on UI thread
//this calls the anonymous delegate in the UI thread
//that then calls the updateLabel function again to set the label's text
label1.BeginInvoke(new MethodInvoker(() => this.updateLabel(value)));
return;
}
label1.Text = value.ToString();
}
public void showNewForm()
{
if(this.InvokeRequired) { // check if on UI thread
this.BeginInvoke(new MethodInvoker(this.showNewForm)); // we need to create the new form on the UI thread
return;
}
var anotherForm = new Form1();
anotherForm.Show();
}
}
class Worker
{
private volatile bool stop = false;
private Form1 form;
public Worker(Form1 form)
{
this.form = form;
}
public bool Stop
{
get
{
return stop;
}
set
{
stop = value;
}
}
public void Start()
{
var thread = new Thread(this.work);
thread.IsBackground = true;
thread.Start();
}
private void work()
{
int i = 0;
while(!stop) {
i++;
Thread.Sleep(100);
form.updateLabel(i);
if(i == 50) {
form.showNewForm(); // call into form
// can also do the invokerequired check here and create new form w/ anonymous functions
// however, I'd recommend keeping all the UI code in the same place.
}
}
}
}