为什么在第二次迭代调用 Hide 后此 winform 不显示?

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

我现在的情况是这样的:

在我的 OnStart/OnStop 方法中,我 initiate/hide 一个 winform,在上下文中它是这样的:

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
    }
}

PluginManager winform 关闭事件被覆盖以调用 Hide() 所以技术上(我假设)我的 winform 永远不会 disposed/closed?

到目前为止,一切都按预期工作,winform 按预期显示在 OnStart 并隐藏在 OnStop。

现在,当我再次启动应用程序 A 并调用 OnStart 方法时,winform 永远不会出现,我没有收到任何错误消息,也没有任何简单的无法打开的内容。

我知道函数被调用了,因为它将调用 Show().

之前和之后的行输出到日志文件

在进一步的测试中,我发现如果我处理 winform 并重新初始化它,winform 将适用于每次调用:

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
}

但是我仍然不知道为什么需要这样做,因为 winform 从未与初始代码一起处理过。

我的情况大概是off-topic?由于我无法为您提供该问题的可重现代码,不幸的是,以上是我所能收集到的所有信息,但希望有人能够为我指明正确的方向或关注的地方。

您提到您的 PluginManager winform 关闭事件被覆盖以调用 Hide(),您是否设置了 e.Cancel = true

    protected override void OnClosing(CancelEventArgs e)
    {
        e.Cancel = true;
        this.Hide();
        base.OnClosing(e);
    }

这可能是线程问题。您应该只从 [STAThread] 调用 .Show(),并且您应该从调用 .Show() 的同一线程调用 .Hide()。所以这样做:

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
    }
}

我不知道应用程序的主体结构如何,但您可以从任何打开的表单中填写 _invoker。

[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);
}

您还可以创建一个完全独立的 STAThread 并调用 Application.Run(_pluginManager) 而不是 pluginManager.Show()。