Reputation: 3482
My current situation is as follow:
Within my OnStart/OnStop method I initiate/hide a winform, in context its something like this:
private static PluginManager _pluginManager;
public static void OnStart()
{
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}
public static void OnStop()
{
if (_pluginManager != null)
{
// some log file code here
_pluginManager.Hide();
// some log file code here
}
}
The PluginManager
winform close event is override to call Hide()
so technically(I assume) my winform will never be disposed/closed?
Everything works as expected so far the winform shows up at OnStart and hides on OnStop as expected.
Now when I start Application A again and it calls the OnStart method, the winform never shows up, I don't get any error messages nor anything it simple doesn't open.
I know the function is called because it outputs to the log file the line before and the line after it calls Show()
.
On further tests I found out that if I dispose of the winform and reinitialize it, the winform will work for every call:
public static void OnStart()
{
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
else
{
_pluginManager.Dispose();
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}
However I am still unaware of why this is required given the winform is never disposed of with the initial code.
My case is probably off-topic? As I can't provide you with a reproducible code of the issue and unhappily the above is all I could collect, but hopefully some one will be able to point me in the right direction or where to look at.
Upvotes: 2
Views: 250
Reputation: 3851
This is probably a threading problem. You should only call .Show() from an [STAThread] and you should call .Hide() from the same thread that called .Show(). So do this:
private static ISynchronizeInvoke _invoker = null;
public static void OnStart()
{
_invoker.Invoke((Action)(() => {
// some log file code here
if (_pluginManager == null)
{
_pluginManager = new PluginManager();
}
// some log file code here
_pluginManager.Show();
// some log file code here
}), null);
}
public static void OnStop()
{
if (_pluginManager != null)
{
// some log file code here
_pluginManager.Invoke((Action)(() => _pluginManager.Hide()));
// some log file code here
}
}
I don't know how the application's main is structured, but you can fill in _invoker from any open form.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1()); <-- This is the usual startup
// Instead, do this to grab an object to invoke on
Form1 form1 = new Form1();
_invoker = form1;
Application.Run(form1);
}
You could also create a wholly separate STAThread and call Application.Run(_pluginManager) instead of pluginManager.Show().
Upvotes: 1
Reputation: 1236
You have mentioned that your PluginManager winform close event is override to call Hide(), did you set e.Cancel = true?
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
base.OnClosing(e);
}
Upvotes: 0