Visual C++/CLI 中的异步睡眠,如何创建一个 X 毫秒来调用函数,而不会使 GUI 也停止
Asynchronous Sleep in Visual C++/Cli, How to create a of X milliseconds to call a function without making the GUI stops too
标题很清楚,我只需要知道是否有办法休眠几毫秒,然后在不停止 GUI 的情况下调用函数。我现在所做的方式只是添加Sleep(3000);
,这使得 GUI 冻结,直到睡眠时间完成。
我尝试在线程中添加Sleep()
然后调用函数,但它不起作用,因为该函数在 GUI 元素中进行修改,而线程不允许您访问 GUI 元素(如标签、按钮......
那么我应该怎么做才能让我的代码等待几秒钟继续,但不停止 GUI?
顺便说一句,睡眠在backgroundWorker_RunWorkerCompleted
内(这只是后台工作者完成后后台工作者的回调)。
void backgroundWorker_RunWorkerCompleted(Object^ /*sender*/, RunWorkerCompletedEventArgs^ e){
printf("Done, Waiting 3 seconds to do something that has to be 3 seconds after.");
Sleep(3000); //at this point the UI freezes
this->CallFunction();
}
关于如何做到这一点的任何提示/建议?
你提到了一个GUI,但没有提到任何特定的UI框架。我暂时假设WinAPI,但从概念上讲,绝大多数其他框架都有我将要提到的内容。
在 Win32 中,可以使用计时器来实现所需的目标。在您的WM_CREATE
或WM_INITDIALOG
等中,使用设置计时器设置计时器。然后,系统会获取您提供的超时值,每次该值经过时,它都会通过WM_TIMER消息通知您的窗口。 SetTimer
会立即返回,因此不会阻止您的 UI 线程。
另一种方法是在开始时启动一个新线程。这个新线程将进行睡眠,并每 3 秒完成一次需要完成的任何工作。由于它是在单独的线程中完成的,因此 UI 不会锁定。您应该始终从WndProc
快速/立即返回。如果需要做很多工作,则应将该工作委托给另一个线程,该线程将完成繁重的工作。
让你的后台线程在主线程上为一个互斥变量设置一个标志,告诉它(主线程)继续做它正在做的事情是安全的。这有点像红绿灯——所有角落(两侧)都有相互关联的灯。
您的主线程不会暂停,但您可以在其中处理(gui 和其他)消息的 while 循环,但在设置互斥变量之前它不会中断循环——这将发生在后台线程上。
以下是一些帮助您入门的参考资料:
- C++中的锁和互斥锁
- 互斥示例/教程?
编辑 -- 根据请求:
全局定义互斥句柄和变量:
HANDLE sharedMemoryMutex = CreateMutex(NULL, FALSE, "My mutex =)!");
BOOL good2Go = false;
然后,在您的后台线程中,它将如下所示:
void wait() {
// First, we sleep...
sleep(3000);
// Now, we request a lock on the good2Go variable, so that when we write to
// it, no other thread is:
DWORD dwWaitResult = WaitForSingleObject(sharedMemoryMutex, INFINITE);
if (dwWaitResult == WAIT_OBJECT_0 || dwWaitResult == WAIT_ABANDONED) {
if (dwWaitResult == WAIT_ABANDONED) {
// Shared memory is maybe in inconsistent state because other program
// crashed while holding the mutex. Check the memory for consistency
...
}
// Access your shared memory
good2Go = true;
// Release the lock so that the main thread can read the variable again..
ReleaseMutex(sharedMemoryMutex);
}
然后在您的主线程中,它将看起来像这样:
// Create your background wait thread:
// .....
while(true) {
// Handle messages so that your program doesn't appear frozen.
// You will have to do your research on this one =)
YourMessageHandler();
// Request a lock on the good2Go variable, so we can read it w/o corrupting it
DWORD dwWaitResult = WaitForSingleObject(sharedMemoryMutex, INFINITE);
if (dwWaitResult == WAIT_OBJECT_0 || dwWaitResult == WAIT_ABANDONED) {
if (dwWaitResult == WAIT_ABANDONED) {
// Shared memory is maybe in inconsistent state because other program
// crashed while holding the mutex. Check the memory for consistency
...
}
// Exit the loop
if( good2Go ) { ReleaseMutex(sharedMemoryMutex); break; }
ReleaseMutex(sharedMemoryMutex);
}
// Continue your code after the 3 pause....
如果您还不知道,则必须弄清楚如何处理消息。此外,您的互斥体实现可能有所不同,但是您说您使用的是VC,因此上面的win32实现应该没问题。我想你明白一般概念
由于您使用的是 VC++/CLI,因此它是 C# 的近亲。您应该查看此处以了解如何从另一个线程更新 GUI:
如何在 C# 中从另一个线程更新 GUI?
快速修复:将Sleep
调用放在BackgroundWorker
任务中,而不是RunWorkerCompleted
事件处理程序中。 事件处理程序在 GUI 线程上运行。
更好的解决方法:了解像迈克建议的计时器。 WinForms 提供了计时器,这些计时器将在您选择的延迟后触发事件。 启动后台任务只是为了让它进入睡眠和退出是一种可怕的浪费。
- 如何用参数值调用函数(仅在运行时已知)
- 从python中调用C++函数并获取返回值
- 当使用通配符和null指针调用函数时,对输出的说明
- 从R调用C++函数并对其进行集成时出错
- 使用QTreeView,如何通过调用函数只突出显示特定的行/列
- 如何在qt中从另一个类调用函数
- 在 COUT 语句中使用 COUT 调用函数
- 如何从线程中的不同模块调用函数?
- C++从函数指针数组调用函数
- 当 A 在 for 循环中调用函数 B 时,如何计算函数 A 的空间复杂度?
- 如何在 C/C++ 中从外部库调用函数
- 如何使用运算符在同一行中多次调用函数
- 是否可以创建一个从不同类调用函数的线程?
- 无法为类成员调用函数
- 如何从另一个标头 c++ 调用函数
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 如何只允许在调用函数 B 后调用函数 A?
- 我可以这样调用函数吗?
- 如何在 c++ 的类中递归调用函数方法?
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?