2010-02-09 57 views
1

我在我的应用程序一些长期的过程,所以我创建了一个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(),但只有任务栏上的框架才会激活,但该应用仍保留在所有应用程序的背面。

对此有何看法?

在此先感谢

+4

我强烈建议你用'HideWait'方法发出的等待句柄(比如'ManualResetEvent')替换你的while循环。这样你就不会使用任何不必要的CPU资源。 – 2010-02-09 14:04:11

+0

当我使用手动或自动重置事件时,应用程序挂起,等待表单不显示等待动画,整个应用程序等待信号。 – Argons 2010-02-09 14:40:13

+0

已经在这里解决了这个问题几次...看看:1. http://stackoverflow.com/questions/2183520/backgroundworkers-never-stop-being-busy/2183963#2183963 2. http:// stackoverflow.com/questions/2152445/displaying-please-wait-message/2153082#2153082 – Oliver 2010-02-09 15:42:36

回答

1

我不能重现其他应用去顶,但与弗雷德里克的建议放弃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(); 
      } 
     }); 
    } 
} 
+0

嗨亲爱的,我需要一个简单的项目为例。 你能帮我发送或给一个链接。 在此先感谢。 [email protected] – Zolfaghari 2014-12-01 11:49:22

0

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

espera.TopMost = true; 

property?

+0

是的我已经设置了属性,等待窗体显示正确,问题与主窗体。 – Argons 2010-02-09 14:01:32

0

我想你想一个模式的形式,尝试

espera.ShowDialog(); 

OTOH我真的不明白你想要,所以我可能是错的。

+0

等待窗体具有TopMost = true,所以ShowDialog()不是必需的 – Argons 2010-02-09 14:07:15

+0

ShowDialog可能是您想要的,因为当任务完成后,主窗体将在等待窗体关闭时获得焦点。 (我认为) – 2010-02-09 14:13:12

+0

我试图使用ShowDialog,但等待窗体进入右上角,仍然主窗体没有焦点。 – Argons 2010-02-09 14:21:07

1

您的代码片段不会为我重现问题。真正重要的是主要形式正在发生什么。你看到发生的事情并不是那么不寻常。等待窗体关闭后,Windows会在您的应用程序中寻找另一个窗口来关注焦点。如果它找不到一个,它会从另一个进程中选择另一个窗口并将其放到前台。实际上,您的主窗体将在该窗口后面消失。

这是保证发生在您的主窗体被禁用时,也许您将其Enabled属性设置为false?我想这也可能发生在你的主窗体仍然对Windows消息没有反应的时候,那一部分是模糊的。

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

1

你尝试使用的Show它接受一个所有者窗口的过载,并通过一null引用它?我所经历的已经解决了这种方式过类似的问题:

espera.Show(null); 

似乎有在调用Show()(这是在类型Control实施的行为的一些差异,简单地设置Visible = true,这在在这种情况下触发Form类型的触发器代码),并调用Show(owner)