2010-02-09 81 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)