所讨论的语言是 Nim,使用 wNim 库,但实际上问题是关于 win32 api,因为 wNim 是 Win32 gui 的一个非常轻量级的包装器。
我有一个单线程程序。当用户单击按钮时,它会启动一个长时间运行的计算。在每个第 n 个周期,计算偶尔会用 更新窗口InvalidateRect
,然后是UpdateWindow
。WM_PAINT
处理程序会立即在屏幕上绘制一些内容。有时我会引入一个sleep
几毫秒的 ,认为这会让系统WM_xxx
消息有时间赶上。
这通常可以正常工作。我可以在客户端区域以图形方式查看计算进度。
但是,当我尝试在更新期间移动窗口时(无论有没有sleep
),它不仅不响应移动(如果sleep(...)
省略,这是可以理解的),而且图形onPaint
完全停止,窗口变成程序死机时 Windows 呈现的幽灵白色。通常,命令行中的调试输出会继续。通常(但并非总是),命令行输出会停止,然后出现 Windows 对话框,告诉我程序崩溃了。我随时都可以在命令行中按 ctrl-c 并恢复正常。有人能解释一下是什么特定的事件序列和处理不当的消息导致一切都惨遭失败吗?
下面是伪代码。有没有一种适当的方法可以让长时间运行的前台计算更新客户端区域,同时响应其他用户事件,而无需多线程?或者多线程是这里最好的选择?我怀疑我的sleep(...)
调用是将一些周期返回到消息传递机制的地方。
伪代码:
proc onButton():
while(stuffNotDone):
doExpensiveStuff()
InvalidateRect(false) # <-- Win32 call
UpdateWindow() # <-- Win32 call
Sleep(10) # <-- Win32 call (optional)
proc onPaint(event):
# Responds to WM_PAINT
var dc = PaintDC(...) # <-- leads to Win32 BeginPaint
dc.blit(...) # <-- leads to Win32 call
SendMessage(hwnd, WM_APP+3,0,0) # <-- Win32 call to clear data elsewhere