Как мне создать вторичный цикл сообщений в vb.net? - PullRequest
2 голосов
/ 26 августа 2010

У меня есть приложение, работающее с полуфоновым материалом в потоке GUI.Другой поток не будет работать, и таймер не будет работать.Но я хочу, чтобы приложение реагировало, пока я выполняю свою «фоновую» работу.

Я могу использовать application.doevents - но это дает мне 3 неправильных варианта:

  • loopбез снов - завершить привязку всего ЦП (моя задача ожидает чего-то еще, кроме calcs & I / O, так что это имеет значение)
  • цикл со сном - тогда приложение замедляется
  • Попробуйте сделать«Умный спящий» цикл, который ускоряется, когда происходит много сообщений (проверьте наличие сообщений в функции фильтра сообщений)

В хорошие ole 'дни в SDK я могу сделать это:

while(PeekMessage(&msg,0,0,0,PM_REMOVE) && still_working)  
{
       TranslateMessage( &msg );
       DispatchMessage(&msg);
      // do a bit of my background work with each message here, quit the loop when done.
}

Хотелось бы, чтобы он был немного лучше, чем DoEvents, поскольку он будет обрабатывать несколько сообщений подряд, но мне все еще нужно использовать «умный сон» для сохранения процессора - я бы хотел этого избежать.

Также есть ли способ сделать основной цикл обработки сообщений?

    MSG msg; 
    while( GetMessage( &msg, NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );

    }

Существует ли правильный эквивалент .NET, или мне просто нужно p / вызвать sdk?Спасибо!

РЕДАКТИРОВАТЬ Winforms.Для всех вас, отвечающих на вопрос, почему я не могу использовать application.run или потоки, я хочу обработать событие OnUnhandledException, а затем оставить приложение открытым на некоторое время, пока некоторые объекты winforms корректно закрывают его и сообщают моемусторожевая программа для перезапуска приложения. после , что также позволяет пользователю завершить критический процесс.Да, я знаю людей, что программа, получившая OnUnhandledException, заслуживает смерти (очевидно, MS), есть «опасные» вещи, которые могут произойти;однако ни один из них не так опасен, как гнев моих пользователей.

Edit # 2 - Ищет исходный код vb.net точных переводов двух вышеупомянутых функций.

Может быть, кто-то, кто хорошс помощью p / invoke и объявляет, может получить быстрое вознаграждение; -)

Ответы [ 5 ]

3 голосов
/ 17 сентября 2010

Если вы полны решимости написать свой собственный цикл сообщений, вы можете.

Application.Run с закрытым исходным кодом, поэтому вы не знаете, что он делает, кроме GetMessage, TranslateMessage и DispatchMessage, так что вам лучше хотя бы позвонить DoEvents. Поскольку DoEvents обрабатывает только ожидающие сообщения и не ждет, вы можете вызвать WaitMessage, чтобы получить процессор, пока не появятся новые сообщения для обработки.

Declare Function WaitMessage Lib "user32.dll" () As Boolean

Shared Sub Main()
    Dim f As New Form1
    f.Show()
    Do While f.Visible
        Try
            Application.DoEvents()
        Catch e As Exception
            MsgBox(e.Message)
        End Try
        WaitMessage()
    Loop
End Sub

Это не завершает привязку ЦП, но также не выполняет фоновую работу.

Вы еще не сказали, какова ваша фоновая работа, но если она выполняется асинхронно, вы должны заменить WaitMessage на MsgWaitForMultipleObjectsEx - хотя вам нужно получить дескрипторы Win32 объекты, которые вы ожидаете.

2 голосов
/ 16 сентября 2010

У вас, кажется, есть две причины желать написать свой собственный цикл сообщений:

1. Чтобы избежать «завершения разметки всего процессора».

Как правило, это достойная цель, но если вы выполняете какие-то вычисления, использование ЦП вполне уместно. Принимая нормальный приоритет процесса, он не остановит другие процессы процессора. Если вы намеренно ограничите свои вычисления, они будут выполняться медленнее, чем это необходимо, раздражая пользователя.

Ваша версия "добрых старых дней", возможно, может быть продублирована в .NET, но я не понимаю, как это могло бы предотвратить завершение работы процессора Как вы думаете, это отличается от вызова Application.DoEvents() в цикле при выполнении вашей "фоновой" работы?

2. Чтобы разрешить обработку «необработанных» исключений.

Возможно, вы захотите обернуть DispatchMessage() (или весь цикл) в блок Try ... Catch. Это не обязательно. Просто сделайте это:

''// file ApplicationEvents.vb
''// <- the stackoverflow syntax highlighter doesn't know about VB comment syntax
Namespace My
    Partial Friend Class MyApplication
        Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
            e.ExitApplication = False
            ''// notify the user or whatever...
        End Sub
    End Class
End Namespace

См. Документы: Событие My.Application.UnhandledException .

2 голосов
/ 26 августа 2010

Если вы используете WinForms, просто используйте API Application.Run() для установки правильного цикла сообщений.

0 голосов
/ 26 августа 2010

Другой поток не будет работать

Почему? Это или BackgroundWorker (использование ThreadPool) - это то, что вам нужно.

0 голосов
/ 26 августа 2010

Взгляните на BackgroundWorker , у меня это хорошо работало в прошлом ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...