我有一个应用程序在GUI线程中处理半背景的东西。另一个线程将无法工作,计时器将无法工作。但我希望应用程序能够在我进行“背景”工作时做出响应。
我想使用application.doevents - 但这给了我3个糟糕的选择:
在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),有可能发生'危险'的事情;然而,没有一个像我的用户的愤怒一样危险。
也许某人对p / invoke和声明很好的人可以得到快速的赏金; - )
答案 0 :(得分:3)
如果您决定编写自己的消息循环,则可以。
Application.Run
是封闭源代码,所以除了GetMessage
,TranslateMessage
和DispatchMessage
之外你不知道它在做什么,所以你最好至少调用{{ 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)
您似乎有两个理由想要编写自己的消息循环:
这通常是一个有价值的目标,但如果你正在进行一些计算,那么使用CPU是完全合适的。假设正常的进程优先级,它不会饿死CPU的其他进程。如果你故意限制你的计算,它会比必要的运行慢,让用户烦恼。
您的“好日子”版本可能会在.NET中重复出现,但我看不出它会如何避免终止CPU。您如何看待它与在执行“背景”工作时在循环中调用Application.DoEvents()
不同?
您可能希望将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
答案 3 :(得分:0)
看看BackgroundWorker,过去对我来说效果很好......
答案 4 :(得分:0)
另一个线程不起作用
为什么呢?那个或BackgroundWorker(ThreadPool用法)是你所需要的。