【问题标题】:"Wait Please" form hides main form“请稍等”表单隐藏主表单
【发布时间】:2010-02-10 00:01:44
【问题描述】:

我的应用程序中有一些很长的进程,所以我创建了一个 WAIT PLEASE 表单并像这样调用另一个线程:

public void ShowWait()
    {
        continueWait = true;
        ThreadPool.QueueUserWorkItem((x) =>
            {
                using (frmWait espera = new frmWait())
                {
                    espera.ShowInTaskbar = false;
                    espera.Show();
                    while (continueWait)
                        Application.DoEvents();
                    espera.Close();
                }
            });
    }

并关闭我使用的表单:

public void HideWait()
    {
        continueWait = false;
    }

它工作正常,但我有一个问题,当显示等待表单时,主表单失去焦点,同时运行的任何其他应用程序(Excel、Word 等)进入顶部,我的应用程序运行到所有应用程序的后面。我尝试使用 Activate() 和 Focus(),但只有任务栏上的框架激活,但应用程序仍位于所有应用程序的背面。

对此有什么启示吗?

提前致谢

【问题讨论】:

  • 我强烈建议您使用在 HideWait 方法中发出信号的等待句柄(例如 ManualResetEvent)替换您的 while 循环。这样您就不会使用任何不必要的 CPU 资源。
  • 当我使用手动或自动重置事件时,应用程序挂起,等待表单不显示等待动画,整个应用程序都在等待信号。
  • 这里已经解决了好几次这个问题了...看看:1.stackoverflow.com/questions/2183520/… 2.stackoverflow.com/questions/2152445/…

标签: c# winforms multithreading


【解决方案1】:

我无法重现其他应用程序,但与 Fredrik 建议放弃 while 循环有关,这对我有用:

AutoResetEvent processing = new AutoResetEvent(false);

private void HideWait()
{
    processing.Set();
}

private void ShowWait()
{           
    ThreadPool.QueueUserWorkItem((x) =>
    {
        using (frmWait espera = new frmWait())
        {
            espera.ShowInTaskbar = false;
            espera.Show();
            processing.WaitOne();
            espera.Close();
        }
    });
}

编辑:

为了避免主窗体失去焦点:

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

static readonly int SW_SHOWNOACTIVATE = 4;

AutoResetEvent processing = new AutoResetEvent(false);

private void HideWait()
{
    processing.Set();
}

private void ShowWait()
{
    ThreadPool.QueueUserWorkItem(c =>
    {
        using (frmWait espera = new frmWait())
        {
            espera.ShowInTaskbar = false;
            ShowWindow(espera.Handle, SW_SHOWNOACTIVATE);
            processing.WaitOne();
            }
        });
    }
}

【讨论】:

  • 您好,亲爱的,例如,我需要一个简单的项目。你能通过发送或提供链接来帮助我吗?提前致谢。 abbas.zolfaghari@gmail.com
【解决方案2】:

您的代码 sn-p 不会为我重现问题。真正重要的是主窗体发生了什么。你看到发生的事情并没有那么不寻常。当您的等待表单关闭时,Windows 会在您的应用程序中寻找另一个窗口以提供焦点。如果找不到,它将从另一个进程中选择另一个窗口并将其带到前台。实际上,您的主窗体将消失在该窗口后面。

当您的主窗体被禁用时,肯定会发生这种情况,也许您将其 Enabled 属性设置为 false?我想当你的主窗体仍然对 Windows 消息没有响应时也会发生这种情况,那部分是模糊的。

通过在后台线程而不是 UI 线程上执行耗时的代码来避免此类问题(以及用于等待表单的不正确的线程单元)。 BackgroundWorker 旨在让这一切变得简单。

【讨论】:

    【解决方案3】:

    您是否尝试过使用接受所有者窗口的Show 的重载,并将空引用传递给它?我过去也遇到过类似的问题,这些问题已经通过这种方式解决了:

    espera.Show(null);
    

    调用Show() 的行为似乎有些不同(在Control 类型中实现,它只是设置Visible = true,在这种情况下又会触发Form 类型的代码) ,并致电Show(owner)

    【讨论】:

      【解决方案4】:

      希望我能正确理解您的问题。所以你想把 WaitForm 设置在最前面?如果是这样,您是否设置了

      espera.TopMost = true;
      

      财产?

      【讨论】:

      • 是的,我设置了属性,等待表单显示正确,问题出在主表单上。
      【解决方案5】:

      我想你想要一个模态表单,试试

      espera.ShowDialog();
      

      我真的不明白你想要什么,所以我可能错了。

      【讨论】:

      • 等待表单的TopMost = true,所以不需要ShowDialog()
      • ShowDialog 可能是您想要的,因为当任务完成时,主窗体将在等待窗体关闭时获得焦点。 (我认为)
      • 我尝试使用 ShowDialog 但等待窗体转到右上角,但主窗体仍然没有焦点。
      猜你喜欢
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多