2011-06-07 36 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优雅地结束线程。
相关问题