2008-11-03 68 views
2
  1. 在一個簡單的winform應用程序中,我調用了一個函數,該函數在一個按鈕單擊事件上無休止地創建文件。我將Application.DoEvents()添加到循環中。停止在winform按鈕上執行的功能點擊

  2. 我按紅色的X來關閉窗體。

  3. 窗體關閉,但文件繼續創建...

我認爲它的按鈕線程,但它不應該是一個背景呢?在循環函數中嘗試將Thread.CurrentThread.IsBackGround更改爲True並沒有幫助。

想法?

回答

5

您使用Application.DoEvents的事實是問題的第一個標誌:它表明您在UI線程中做得太多。在一個結構良好的計劃中幾乎是不合適的。 UI線程並不意味着有任何長時間運行的任務。 (不可否認,如果繪製UI需要很長時間,你沒有多少選擇 - 但這表明你應該簡化你的UI ...並且在這種情況下它不適用,我懷疑它。)

而應該執行長時間運行的任務(創建文件)在一個單獨的線程中。 BackgroundWorker是這一個完美的結合 - 你可以用它來報告進度回到UI,並且UI可以調用CancelAsync方法,要求它停止。你需要從工作線程內檢查CancellationPending屬性,看看是否取消已請求,並適當地停止。

編輯:只是爲了澄清我相信發生了什麼 - 我懷疑你的表單正在關閉,但程序不會終止,直到事件循環完成。你正在使用你的文件創建循環來保持事件循環,因此就是問題所在。

請注意,該按鈕沒有線程 - 只有一個用於整個UI。 (在某些情況下,您可能需要多個UI線程,但這種情況非常少見 - 如果您已完成這項工作,您會知道它的。)

+0

謝謝你的時間。我知道有不同的,更好的方法來做到這一點,我想明白爲什麼這個不起作用(最優與否) – gil 2008-11-03 19:52:42

+0

我的編輯幫助嗎?基本上,直到你讓按鈕單擊處理程序完成,應用程序不會停止(除非你使用像Thread.Abort這樣可怕的東西) – 2008-11-03 19:54:14

+0

好吧,再多一個Q,你說「請注意,沒有線程按鈕 - 只有一個用於你的整個UI「::當我按下紅色X時,調試器跳轉到配置。在什麼線程完成?因爲用戶界面正在忙於循環... – gil 2008-11-03 20:01:34

0

您是否特別爲該ButtonClick代碼創建了新線程?如果不是,那麼它的同一個線程的形式,因此,「X」按鈕應該停止。

無論哪種情況,您都可以設置一個標誌(isClosing),並在「while true」循環中檢查該標誌。

0

你嘗試調用Thread.CurrentThread.Abort()? 這是不推薦的方式,但如果你沒有從功能訪問功能s source code it might help (even though you say you are calling DoEvents`)。

如果您確實有權訪問源代碼,那麼您可以在那裏進行檢查,讓循環知道它必須停止。

此外,可以使用的background worker部件,或者創建一個不同的線程,並且從外部控制它(即,從表格)

1

A按鈕點擊處理程序執行在UI線程上。

當你調用Application.DoEvents,你讓UI線程進程窗口消息。其中一個影響是每次用戶點擊該按鈕時,點擊處理程序方法的新「實例」(堆棧框架)以及其他很多堆棧框架都會添加到堆棧中。像這樣:

{windows forms methods incl. message pump} 
    **ClickHandler** 
    Application.DoEvents 
    {windows forms methods incl. message pump} 
     **ClickHandler** 
     Application.DoEvents 
     {windows forms methods incl. message pump} 
      etc. 

這一切都非常可怕。

如果你想在後臺運行的代碼,更好的選擇是使用

  • BackgroundWorker組件。
  • 標準的基於.NET委託的機制(BeginInvoke,EndInvoke,IAsyncResult等)用於在線程池中運行代碼。
  • 如果你想要實現一個長時間運行的後臺線程,而不是將一塊'工作'分配給池,你可以創建並啓動一個線程,該線程被設置爲後臺線程。
1

這種形式級變量添加到您的窗體的代碼:

private bool _StillOpen = true; 

然後包裹無盡的循環代碼在你點擊鏈接是這樣的:

while (_StillOpen) 
{ 
    // do whatever your method does 
    Application.DoEvents(); 
} 

最後,添加以下代碼到您的表單的FormClosing事件:

_StillOpen = false; 

這將全部當你點擊關閉按鈕時,你的窗體將關閉。理想情況下,你會希望像這樣的東西在後臺線程上執行,但這種標誌方法可能是對當前問題的快速修復。