4

独自のスレッドで実行される単純な「作業中」フォームがあり、長時間実行されている操作中にアプリケーションが停止していないことをユーザーに通知します。作業フォームを更新するには、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
4

2 に答える 2

3

DoEvents現在のUIスレッドのみをポンピングします。

ただし、私はあなたのアプローチをお勧めしません。

代わりに、バックグラウンドスレッドで作業を行い、UIスレッドにモーダルプログレスフォームを表示し、BeginInvokeまたはを使用して更新する必要がありBackgroundWorkerます。

于 2011-06-07T14:46:34.423 に答える
2

DoEvents呼び出されたスレッドにのみ影響します。そのスレッドに投稿されたすべてのWindowsメッセージをデキューし、それに応じてディスパッチします。すべてのメッセージがディスパッチされた後、それは発信者に戻ります。

しかし、私はあなたのコードについて他にいくつかの観察を持っています。

  • 基本的に、ループ内で繰り返し呼び出すことにより、メッセージループの独自の機能不全バージョンを作成DoEventsしました。Application.Run完全なメッセージループを開始するために呼び出すだけの方がよいでしょう。
  • メインUIスレッド以外のスレッドでメッセージループを作成することは、めったに良い考えではありません。対処するのが難しいいくつかの奇妙なことが起こります。たとえば、あるスレッドのモーダルダイアログボックスが別のスレッドのモーダルダイアログボックスと重なる場合があります。
  • ThreadAbortExceptionほとんどの場合、aをキャッチしようとしても意味がありません。この例外が発生した場合は、AppDomain全体の状態が破損している可能性があります(おそらく可能性があります)。アプリケーションドメインを適切に処理しようとするよりも、アプリケーションドメインを破棄する方が適切です。これは、スレッドの実行中の任意の時点で例外が挿入される可能性があり、それらの挿入ポイントが途中または書き込み、長時間の操作、またはその他の安全でないポイントにある可能性があるためです。
  • 上記の結果として、Thread.Abort別のスレッドを終了するために使用しないでください。うまくいかないことが多すぎます。より安全なメカニズムを使用して、スレッドを正常に終了させることをお勧めします。
于 2011-06-07T17:28:42.233 に答える