代码之家  ›  专栏  ›  技术社区  ›  FastAl

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

  •  2
  • FastAl  · 技术社区  · 14 年前

    我在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.
    }
    

    wnd比doEvents好一点,因为它将连续处理多条消息,但我仍然必须使用“智能睡眠”来节省CPU—我想避免这种情况。

    还有一种方法来做一个主消息循环吗?

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

    是否有一个适当的.NET等价物,或者我只需要p/invoke sdk工具? 谢谢!

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

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

    也许一个善于使用P/Invoke和声明的人可以得到一个快速的赏金;-)

    5 回复  |  直到 14 年前
        1
  •  3
  •   Hugh Allen    14 年前

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

    Application.Run 是封闭源代码,所以你不知道它在做什么 GetMessage , TranslateMessage DispatchMessage 所以你最好至少打个电话 DoEvents 相反。自从 事件发生 只处理挂起的消息,不等待,您可以调用 WaitMessage 以产生CPU,直到有新的消息要处理。

    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
    

    这并没有结束绑定CPU,但它也不做任何后台工作。

    你还没有说你的背景工作到底是什么,但是如果是异步完成的东西,你应该替换它。 等待消息 具有 MsgWaitForMultipleObjectsEx -尽管您需要获取正在等待的对象的win32句柄。

        2
  •  2
  •   JaredPar    14 年前

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

        3
  •  2
  •   Hugh Allen    14 年前

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

    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 .

        4
  •  0
  •   joshperry    14 年前

    看一看 BackgroundWorker 过去对我很好…

        5
  •  0
  •   TomTom    14 年前

    另一条线不行

    为什么?或者backgroundworker(threadpool用法)就是您所需要的。