DoEvents влияет только на текущий поток? - PullRequest
4 голосов
/ 07 июня 2011

У меня есть простая «рабочая» форма, которая запускается в своем собственном потоке, чтобы держать пользователя в курсе, что приложение не умерло во время длительных операций.Чтобы получить рабочую форму для обновления, мне пришлось вставить вызов 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

Ответы [ 2 ]

3 голосов
/ 07 июня 2011

DoEvents будет перекачивать только текущий поток пользовательского интерфейса.

Однако я не рекомендую ваш подход.

Вместо этого вы должны выполнить свою работу в фоновом потоке и показатьмодальную форму прогресса в потоке пользовательского интерфейса и обновите ее, используя BeginInvoke или BackgroundWorker.

1 голос
/ 07 июня 2011

DoEvents влияет только на поток, из которого он вызывается. Он удалит все сообщения Windows, опубликованные в этой теме, и отправит их соответствующим образом. После того, как все сообщения будут отправлены, он вернется обратно к вызывающей стороне.

У меня есть пара других замечаний относительно вашего кода.

  • Вы в основном создали свою собственную ограниченную версию цикла сообщений, многократно вызывая DoEvents в цикле. Было бы лучше просто позвонить Application.Run, чтобы инициировать полный цикл сообщений.
  • Создание цикла сообщений в потоке, отличном от основного потока пользовательского интерфейса, редко бывает хорошей идеей. Есть некоторые странные вещи, с которыми трудно иметь дело. Например, модальное диалоговое окно из одного потока может перекрывать модальное диалоговое окно из другого.
  • Попытка поймать ThreadAbortException бессмысленна в большинстве ситуаций. Если вы когда-либо получите это исключение, то возможно (возможно, даже вероятно), что состояние всего AppDomain было повреждено. Лучше разрушить домен приложения, чем пытаться изящно с ним справиться. Это связано с тем, что исключение может быть внедрено в любой точке во время выполнения потока, и эти точки внедрения могут находиться в середине или записи, длительной операции или, в противном случае, в некоторой небезопасной точке.
  • В качестве следствия к вышеприведенному пункту не используйте Thread.Abort для завершения другого потока. Есть слишком много вещей, которые могут пойти не так. Лучше сделать так, чтобы поток завершался изящно, используя более безопасные механизмы .
...