2011-06-07 37 views
4

我有一個簡單的「工作」表單,它在自己的線程上運行,以保持用戶通知應用程序在長時間運行操作期間沒有死亡。爲了讓工作表更新,我必須插入一個DoEvents()呼叫。DoEvents是否僅影響當前線程?

我很好奇,這隻會爲當前線程泵送消息,還是會爲整個應用程序執行?我希望主窗口在操作完成之前保持無響應狀態,所以我很好奇行爲。以下是工作表格的代碼。

只是要清楚,我很好,我有代碼,但我想知道DoEvents()行爲與線程。

Public Class frmWorking 

    ''' <summary> 
    ''' Creates and starts a new thread to handle the Working Dialog 
    ''' </summary> 
    ''' <returns>The thread of the Working dialog.</returns> 
    ''' <remarks></remarks> 
    Public Shared Function StartWait() As WorkingFromToken 
     Dim th As New Threading.Thread(AddressOf ShowWait) 
     Dim token As New WorkingFromToken 
     th.Start(token) 
     Return token 
    End Function 

    Private Shared Sub ShowWait(token As WorkingFromToken) 
     Dim frm As New frmWorking 
     Try 
      frm.Show() 
      Do 
       If frm.txtWait.Text.Length > 45 Then 
        frm.txtWait.Text = "Working" 
       Else 
        frm.txtWait.Text &= "." 
       End If 
       Windows.Forms.Application.DoEvents() 
       Threading.Thread.Sleep(250) 
      Loop While token.Running 
      frm.Hide() 

     Catch ex As Threading.ThreadAbortException 
      Threading.Thread.ResetAbort() 
      frm.Hide() 
      Return 
     End Try 

    End Sub 

End Class 
+0

擁有多個UI線程並不是一個好主意。 – SLaks 2011-06-07 14:46:19

+0

即使在你的控制環境中,「Abort」也是危險的,應該避免。輪詢「取消」標誌更安全。 – SLaks 2011-06-07 14:48:09

+0

@SLacks,其實我只是改變了這種方法,我想我只是留在那裏的catch,因爲我不確定是否有其他生成的ThreadAbortException,除了顯式調用Thread.Abort。 – Kratz 2011-06-07 14:54:02

回答

3

DoEvents只會泵當前UI線程。

不過,我不建議你的方法。

相反,您應該在後臺線程上完成您的工作,並在UI線程上顯示模式進度表並使用BeginInvokeBackgroundWorker對其進行更新。

+0

有多個UI線程的具體問題是什麼?不是我不相信你,但我喜歡儘可能多地瞭解我。 – Kratz 2011-06-07 15:01:06

+0

http:// stackoverflow。4793283/two-ui-thread-in-c-windows-application/4793854#4793854 – SLaks 2011-06-07 15:08:49

+0

提高GUI線程以報告長時間運行操作似乎有點奇怪。更經常地將這些操作脫線,以便應用程序主線程可以響應UI消息。至於Application.DoEvents,我從來沒有在VB,C#或Delphi中使用過這樣的東西。據推測,你在這裏需要它,因爲你正在循環你的單獨的GUI線程的事件處理程序/ WndProc? – 2011-06-07 15:21:57

1

DoEvents只會影響調用它的線程。它會將所有發佈到該線程的窗口消息出隊並相應地發送它們。所有消息發出後,它將返回給調用者。

我有一對夫婦的其他意見的有關您的代碼雖然。

  • 你已經基本上通過在循環中調用DoEvents重複創建一個消息循環的自己殘缺的版本。只需撥打Application.Run來啓動一個完整的消息循環會更好。
  • 在主UI線程以外的線程上創建消息循環很少是個好主意。有些奇怪的事情很難處理。例如,一個線程中的模態對話框可能與另一個模態對話框重疊。
  • 試圖趕上ThreadAbortException在大多數情況下沒有意義。如果你得到這個異常,那麼有可能(甚至可能)整個AppDomain的狀態已被破壞。拆除應用程序域比嘗試妥善處理它要好。這是因爲可能在線程執行期間的任何時候注入異常,這些注入點可能在中間或寫入,冗長的操作或其他不安全的地方。
  • 作爲一個必然結果點以上不使用Thread.Abort終止另一個線程。有太多可能出錯的事情。最好使用safer mechanisms優雅地結束線程。
相關問題