Does DoEvents effect only the current thread?

2019-06-24 14:55发布

I have a simple 'Working' form that runs on its own thread to keep the user informed that the application hasn't died during long running operations. In order to get the working form to update I had to insert a DoEvents() call.

I'm curious, will this only pump messages for the current thread I'm in, or will it do it for the whole application? I would prefer that the main window stay unresponsive till the operation finishes, so I'm curious as to the behavior. Below is the code for the working form.

Just to be clear, I'm fine with the code I have, but I would like to know how DoEvents() behaves with threads.

    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

2条回答
Lonely孤独者°
2楼-- · 2019-06-24 15:23

DoEvents will only pump the current UI thread.

However, I do not recommend your approach.

Instead, you should do your work on a background thread, and show a modal progress form on the UI thread and update it using BeginInvoke or a BackgroundWorker.

查看更多
女痞
3楼-- · 2019-06-24 15:28

DoEvents will only effect the thread from which it is called. It will dequeue all windows messages posted to that thread and dispatch them accordingly. After all messages have been dispatched it will return back to the caller.

I have a couple of other observations about your code though.

  • You have basically created your own crippled version of a message loop by calling DoEvents repeatedly in a loop. It would be better to just call Application.Run to initiate a full blown message loop.
  • Creating a message loop on a thread other than the main UI thread is rarely a good idea. There are some weird things that occur that are hard to deal with. For example, a modal dialog box from one thread could overlap a modal dialog box from another.
  • Attempting to catch a ThreadAbortException is pointless in most situation. If you ever get this exception then it is possible (perhaps even likely) that the state of the entire AppDomain has been corrupted. It is better to tear down the application domain than to try to gracefully deal with it. This is because the exception could be injected at any point during the execution of the thread and those injection points could be in the middle or a write, a lengthy operation, or otherwise some unsafe point.
  • As a corollary to the point above do not use Thread.Abort to terminate another thread. There are many too many things that can go wrong. It is better to cause the thread to end gracefully using safer mechanisms.
查看更多
登录 后发表回答