I am developing a plugin for an application that allows additional forms to be created. Some of the plugins are strictly "run-it-and-forget-it" workers, but some have a UI for further control. The plugin exposes an API (via .dll) that shall be subclassed (via their Core class). It has a method that initializes the plugin, as well as a method that shuts down the plugin.
What I'm wanting to do is have the worker thread on the main thread, and the UI thread on another thread that I can send events to as well as receive control events from (start, stop, etc.)
My current implementation has the UI successfully updating; unfortunately, BeginInvoke is of no use because the form is being initialized on my main thread even though it is instantiated and shown in the child thread.
Why is this causing the GUI thread to be blocked when I call form1.UpdateScanningProgress(i)
? It appears that this.InvokeRequired is always false in the example below, even though I'm running the form in another thread.
Here is the "main" code. Note that the plugin information has been stripped. I'm wanting to be as basic as possible:
namespace TestBed
{
class TestBedManager : PluginManager
{
Form1 form1;
void UIInitialized(object sender, EventArgs e)
{
}
void BeginScan(object sender, EventArgs e)
{
for (int i = 0; i <= 100; ++i)
{
Thread.Sleep(150);
form1.UpdateScanningProgess(i);
}
Thread.Sleep(1000);
}
// Parent calls when plugin starts
public void PluginStart()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form1 = new Form1();
form1.Initialized += Initialized;
form1.BeginScan += BeginScan;
Thread thread = new Thread(() =>
{
Application.Run(form1);
});
thread.Start();
// Here is where I'd start my real work instead of simply joining
thread.Join();
}
// Parent calls when plugin needs to stop
public void PluginStop()
{
}
}
}
Here is the Form code:
namespace TestBed
{
public partial class Form1 : Form
{
public event EventHandler Initialized;
public event EventHandler BeginScan;
public Form1()
{
InitializeComponent();
}
delegate void UpdateScanningProgressDelegate(int progressPercentage);
public void UpdateScanningProgress(int progressPercentage)
{
if (this.InvokeRequired)
{
UpdateScanningProgressDelegate updateScanningProgress = new UpdateScanningProgressDelegate(UpdateScanningProgress);
updateScanningProgress.BeginInvoke(progressPercentage, null, null);
}
else
{
this.scanProgressBar.Value = progressPercentage;
}
}
delegate void StopScanningDelegate();
public void StopScanning()
{
if (this.InvokeRequired)
{
StopScanningDelegate stopScanning = new StopScanningDelegate(StopScanning);
stopScanning.BeginInvoke(null, null);
}
else
{
this.scanProgressBar.Value = 0;
}
}
private void Form1_Load(object sender, EventArgs e)
{
if (Initialized != null)
Initialized(this, EventArgs.Empty);
}
private void scanButton_Click(object sender, EventArgs e)
{
if (BeginScan != null)
BeginScan(this, EventArgs.Empty);
}
}
}
I feel that I'm probably missing a small detail and would appreciate an extra pair of eyes.