如何编写使用回调函数的响应式进度条?

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(); 移动到一个单独的线程中,并让您的回调函数将一条消息放入消息循环中(通过SendMessagePostMessage),然后处理该消息并更新进度条.

【讨论】:

thirdpartydriver->DoReallyLongTask() 确实在主 UI 线程上运行,因为代码中没有多线程。但是把进度条放到单独的线程里不是更简单吗? 它可能更简单,但它不会解决你的问题。要获得响应式 UI,您必须将控制权返回给消息循环。这就是 Windows 的工作原理。 我是多线程新手 - 我在问题中添加了一些代码:“我可以将它添加到 ProgressFuncC 代码中吗……”您认为这可以解决无响应问题吗? 是的,这会有所帮助。让它成为一个while循环而不是if,可能会有多条消息。

以上是关于如何编写使用回调函数的响应式进度条?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi DLL 和 Delphi EXE 之间的回调功能

用js写一个网页进度条

C#中调用C的DLL中的回调函数,想实现消息响应机制

如何等待 react native Image Picker 回调函数响应?

tkinter(多个Button对应同一个回调函数如何识别响应的是哪个Button?)

从mongoDB集合中获取N条最新记录时的回调函数[重复]