Guapo
Guapo

Reputation: 3482

Why this winform does not show up after Hide is called on its second iteration?

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

Answers (2)

Moby Disk
Moby Disk

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

Joel Legaspi Enriquez
Joel Legaspi Enriquez

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

Related Questions