You can do it like this:
In Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace TwoWindows
{
static class Program
{
public static Form1 form1;
public static Form2 form2;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form1 = new Form1();
form2 = new Form2();
form1.Form2Property = form2;
form2.Form1Property = form1;
form1.Show();
form2.Show();
Application.Run();
}
}
}
In Form1.cs:
namespace TwoWindows
{
public partial class Form1 : Form
{
public Form2 Form2Property { get; set; }
public Form1()
{
InitializeComponent();
}
protected override void OnClosed(EventArgs e)
{
if (Form2Property.IsDisposed)
Application.Exit();
}
}
}
And Form2.cs:
namespace TwoWindows
{
public partial class Form2 : Form
{
public Form1 Form1Property { get; set; }
public Form2()
{
InitializeComponent();
}
protected override void OnClosed(EventArgs e)
{
if (Form1Property.IsDisposed)
Application.Exit();
}
}
}
This way you can get two forms on the same thread and use one to control the other one.
If you need to use threads I would suggest to use dedicated threads that are part of the classes an not spawn in a method that can be called more than once. Then use ManualResetEvent or AutoResetEvent to control the thread processing. I really like the approach of using something like this, because is safe and doesn't spend much resources initialising threads.
public class MyClassOrForm
{
Thread myProcessingThread;
public AutoResetEvent startProcessing = new AutoResetEvent(false);
public AutoResetEvent processingFinished = new AutoResetEvent(false);
public AutoResetEvent killProcessingThread = new AutoResetEvent(false);
public MyClassOrForm()
{
myProcessingThread = new Thread(MyProcess);
}
private void MyProcess()
{
while (true)
{
if (startProcessing.WaitOne())
{
// Do processing here
processingFinished.Set();
}
if (killProcessingThread.WaitOne(0))
return;
}
}
}
Then, once you have set the data to be processed, call form another class or method
MyClassOrMethodInstance.startProcessing.Set();
And if you need to wait for that processing to finish then insert:
MyClassOrMethodInstance.processingFinished.WaitOne(time_out_ms);
This is equivalent to a Thread.Join() call, only that you wont have to allocate another thread every time with the risks that threads entails if they depend on local data or unfinished child threads.