1

标题很清楚,我只需要知道是否有办法让睡眠几毫秒,然后在不停止 GUI 的情况下调用一个函数。我现在所做的只是添加Sleep(3000);,这会使 GUI 冻结,直到睡眠时间完成。

我尝试添加Sleep()一个线程,然后调用一个函数,但它不起作用,因为该函数在 GUI 元素中进行了修改,并且线程不允许您访问 GUI 元素(如标签、按钮......) .

那么我应该怎么做才能让我的代码等待几秒钟才能继续,但不停止 GUI?

顺便说一句, Sleep 在 a 内部backgroundWorker_RunWorkerCompleted(这只是 backgroundworker 完成后 BackgroundWorker 的回调)。

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();     

}

有关如何执行此操作的任何提示/建议?

4

4 回答 4

1

你提到了一个 GUI,但没有提到任何特定的 UI 框架。我暂时假设 WinAPI,但从概念上讲,绝大多数其他框架都有我将要提到的内容。

在 Win32 中,你可以使用定时器来实现你想要的。在您的WM_CREATEorWM_INITDIALOG等​​中使用SetTimer设置一个计时器。然后系统将获取您提供的超时值,并且每次该值过去时,它都会通过WM_TIMER消息通知您的窗口。SetTimer立即返回,因此不会阻塞您的 UI 线程。

您可以这样做的另一种方法是在开始时启动一个新线程。这个新线程将进行睡眠并每 3 秒执行一次需要完成的任何工作。由于它是在单独的线程中完成的,因此 UI 不会锁定。您应该始终快速/立即从WndProc. 如果需要完成大量工作,则应将该工作委托给另一个线程,该线程将完成繁重的工作。

于 2012-04-10T15:37:06.293 回答
0

由于您使用的是 VC++/CLI,因此它是 C# 的近亲。您应该在这里查看如何从另一个线程更新 GUI:

如何从 C# 中的另一个线程更新 GUI?

于 2012-04-10T16:14:12.783 回答
0

快速修复:将您的Sleep调用放在BackgroundWorker任务中,而不是在RunWorkerCompleted事件处理程序中。事件处理程序在 GUI 线程上运行。

更好的解决方法:了解 Mike 建议的计时器。WinForms 提供了计时器,这些计时器将在您选择的延迟后触发事件。启动后台任务只是为了让它休眠并退出是一种可怕的浪费。

于 2012-04-10T16:18:23.783 回答
0

让你的后台线程在你的主线程上为一个互斥变量设置一个标志,告诉它(主线程)可以安全地继续做它正在做的事情。它有点像一个停车灯——所有角落(两侧)都有相互关联的灯。

您的主线程不会暂停,但您可以有一个 while 循环来处理(gui 和其他)消息,但在设置互斥变量 get 之前它不会中断循环——这将发生在后台线程上。

以下是一些帮助您入门的参考资料:

编辑——根据请求:

在全局范围内,定义您的互斥量句柄和变量:

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 实现应该没问题。而且我认为您了解一般概念

于 2012-04-10T14:10:18.477 回答