如何编写使用回调函数的响应式进度条?
Posted
技术标签:
【中文标题】如何编写使用回调函数的响应式进度条?【英文标题】:How to code a responsive progress bar that uses callback functions? 【发布时间】:2009-12-08 19:03:05 【问题描述】:我有这个进度条,它使用来自第三方驱动程序的回调函数,在名为 CFProgress 的窗口中显示传统进度条。
CFProgress *cFM=new CFProgress();
theApp.m_cFM = cFM;
cFM->Create(CFProgress::IDD);
cFM->ShowWindow(SW_SHOW);
thirdpartydriver->set_OnProgress(ProgressFuncC, (void *) cFM);
thirdpartydriver->DoReallyLongTask();
ProgressFuncC
如下:
void _stdcall ProgressFuncC(CallbackDataType UserData, LongWord Operation, LongWord Progress, LongWord Total, Bool CanStop, Bool *Stop)
char cMsg[100];
sprintf_s(cMsg, 100, "Task Progress (%d%% completed).", Progress * 100 / Total);
CFProgress *cFM;
cFM = theApp.m_cFM;
cFM->m_Prg1.SetPos(Progress * 100 / Total);
cFM->m_lblMsg.SetWindowText(cMsg);
cFM->UpdateWindow();
这在早期的操作系统上运行良好,但 Windows 7 一直抱怨应用程序在显示进度条窗口时没有响应。实际功能不受影响。
有什么好方法可以让它对 Windows 更敏感?
我可以将它添加到ProgressFuncC
代码中并期望它解决问题,还是我只是在这里感到困惑:
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
if (msg.message == WM_QUIT)
::PostMessage(NULL, WM_QUIT, 0, 0L);
else
::TranslateMessage(&msg);
::DispatchMessage(&msg);
【问题讨论】:
【参考方案1】:thirdpartydriver->DoReallyLongTask();
是否在主 UI 线程上运行?
如果是,那么在您将控制权返回给消息循环之前,您的窗口不会响应。
除非此循环正在运行,否则您的任何窗口都不会响应,并且如果该长任务在主线程上,那么它将阻塞此循环。
while(GetMessage(&Msg, NULL, 0, 0) > 0)
TranslateMessage(&Msg);
DispatchMessage(&Msg);
您最好的选择是将您的thirdpartydriver->DoReallyLongTask();
移动到一个单独的线程中,并让您的回调函数将一条消息放入消息循环中(通过SendMessage
或PostMessage
),然后处理该消息并更新进度条.
【讨论】:
thirdpartydriver->DoReallyLongTask() 确实在主 UI 线程上运行,因为代码中没有多线程。但是把进度条放到单独的线程里不是更简单吗? 它可能更简单,但它不会解决你的问题。要获得响应式 UI,您必须将控制权返回给消息循环。这就是 Windows 的工作原理。 我是多线程新手 - 我在问题中添加了一些代码:“我可以将它添加到 ProgressFuncC 代码中吗……”您认为这可以解决无响应问题吗? 是的,这会有所帮助。让它成为一个while循环而不是if,可能会有多条消息。以上是关于如何编写使用回调函数的响应式进度条?的主要内容,如果未能解决你的问题,请参考以下文章
Delphi DLL 和 Delphi EXE 之间的回调功能
如何等待 react native Image Picker 回调函数响应?