如何在vb.net中创建辅助消息循环?

时间:2010-08-26 19:42:19

标签: .net vb.net winforms winapi sdk

我有一个应用程序在GUI线程中处理半背景的东西。另一个线程将无法工作,计时器将无法工作。但我希望应用程序能够在我进行“背景”工作时做出响应。

我想使用application.doevents - 但这给了我3个糟糕的选择:

  • 循环没有睡眠 - 结束整个CPU(我的任务等待除了计算和I / O以外的东西所以这很重要)
  • 循环播放 - 然后应用程序放慢速度
  • 尝试制作一个“智能睡眠”循环,当大量消息发生时加速(检查messagefilter函数中的消息)

在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好一点,因为它会连续处理多个消息,但我仍然需要使用'智能睡眠'来保存cpu - 我想避免这种情况。

还有办法进行主要的消息循环吗?

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

    }

是否有正确的.NET等价物,或者我只需要调用sdk的东西? 谢谢!

编辑 Winforms。对于所有你的答案者,我想知道为什么我不能使用application.run或线程,我想要做的是处理OnUnhandledException事件,然后让我的应用程序打开一段时间,而一些winforms的东西优雅地关闭它并告诉我看门狗程序重启应用程序。 之后允许用户完成关键过程。是的,我知道一个程序得到OnUnhandledException的人应该死(显然是MS),有可能发生'危险'的事情;然而,没有一个像我的用户的愤怒一样危险。

编辑#2 - 寻找上述两个函数的vb.net源代码精确翻译。

也许某人对p / invoke和声明很好的人可以得到快速的赏金; - )

5 个答案:

答案 0 :(得分:3)

如果您决定编写自己的消息循环,则可以。

Application.Run是封闭源代码,所以除了GetMessageTranslateMessageDispatchMessage之外你不知道它在做什么,所以你最好至少调用{{ 1}}而不是。由于DoEvents仅处理挂起的消息而不等待,因此您可以调用DoEvents来生成CPU,直到有新消息要处理为止。

WaitMessage

这不会终止CPU,但它也不会做任何后台工作。

你还没有说明你的后台工作是什么,但是如果它是异步完成的东西你应该用MsgWaitForMultipleObjectsEx替换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 - 尽管你需要获取对象的Win32句柄你在等。

答案 1 :(得分:2)

如果您使用的是WinForms,那么只需使用Application.Run() API设置正确的消息循环即可。

答案 2 :(得分:2)

您似乎有两个理由想要编写自己的消息循环:

1。避免“终止整个CPU”。

这通常是一个有价值的目标,但如果你正在进行一些计算,那么使用CPU是完全合适的。假设正常的进程优先级,它不会饿死CPU的其他进程。如果你故意限制你的计算,它会比必要的运行慢,让用户烦恼。

您的“好日子”版本可能会在.NET中重复出现,但我看不出它会如何避免终止CPU。您如何看待它与在执行“背景”工作时在循环中调用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 Event

答案 3 :(得分:0)

看看BackgroundWorker,过去对我来说效果很好......

答案 4 :(得分:0)

  

另一个线程不起作用

为什么呢?那个或BackgroundWorker(ThreadPool用法)是你所需要的。