windows 为 while 循环创建超时的最干净方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2135981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:49:06  来源:igfitidea点击:

What is the cleanest way to create a timeout for a while loop?

c++cwindowsalgorithmwinapi

提问by T.T.T.

Windows API/C/C++

视窗 API/C/C++

1. ....  
2. ....
3. ....    
4.    while (flag1 != flag2)
5.    {
6.      SleepEx(100,FALSE);   
        //waiting for flags to be equal (flags are set from another thread).
7.    }
8. .....
9. .....  

If the flags don't equal each other after 7 seconds, I would like to continue to line 8.

如果 7 秒后标志不相等,我想继续第 8 行。

Any help is appreciated. Thanks.

任何帮助表示赞赏。谢谢。

回答by JaredPar

If you are waiting for a particular flag to be set or a time to be reached, a much cleaner solution may be to use an auto / manual reset event. These are designed for signalling conditions between threads and have very rich APIs designed on top of them. For instance you could use the WaitForMultipleObjects API which takes an explicit timeout value.

如果您正在等待设置特定标志或等待时间到达,更简洁的解决方案可能是使用自动/手动重置事件。它们是为线程之间的信号条件而设计的,并在它们之上设计了非常丰富的 API。例如,您可以使用采用显式超时值的 WaitForMultipleObjects API。

回答by Michael

Do not poll for the flags to change. Even with a sleep or yield during the loop, this just wastes CPU cycles.

不要轮询要更改的标志。即使在循环期间有睡眠或产量,这只会浪费 CPU 周期。

Instead, get the thread which sets the flags to signal you that they've been changed, probably using an event. Your wait on the event takes a timeout, which you can tweak to allow waiting of 7 seconds total.

相反,获取设置标志的线程以通知您它们已被更改,可能使用event。您对事件的等待需要超时,您可以调整以允许总共等待 7 秒。

For example:

例如:

Thread1:

 flag1 = foo;
 SetEvent(hEvent);


 Thread2:

 DWORD timeOutTotal = 7000;  // 7 second timeout to start.
 while (flag1 != flag2 && timeOutTotal > 0)
 {
     // Wait for flags to change
     DWORD start = GetTickCount();

     WaitForSingleObject(hEvent, timeOutTotal);

     DWORD end = GetTickCount();

    // Don't let timeOutTotal accidently dip below 0.
    if ((end - start) > timeOutTotal)
    {
        timeOutTotal = 0;
    }
    else
    {
       timeOutTotal -= (end - start);
    }

 }

回答by Pete Kirkham

You failed to mention what will happen if the flags are equal.

你没有提到如果标志相等会发生什么。

Also, if you just test them with no memory barriers then you cannot guarantee to see any writes made by the other thread.

此外,如果您只是在没有内存障碍的情况下测试它们,那么您不能保证看到其他线程所做的任何写入。

Your best bet is to use an Event, and use the WaitForSingleObjectfunction with a 7000 millisecond time out.

最好的办法是使用事件,并使用WaitForSingleObject7000 毫秒超时的函数。

回答by Kornel Kisielewicz

You can use QueryPerformanceCounterfrom WinAPI. Check it before while starts, and query if the amount of time has passed. However, this is a high resolution timer. For a lower resolution use GetTickCount(milliseconds).

您可以使用WinAPI 中的QueryPerformanceCounter。在while开始之前检查它,并查询是否已经过去了。然而,这是一个高分辨率计时器。对于较低的分辨率,请使用GetTickCount(毫秒)。

All depends whether you are actively waiting (doing something) or passively waiting for an external process. If the latter, then the following code using Sleepwill be a lot easier:

一切都取决于您是主动等待(做某事)还是被动等待外部进程。如果是后者,那么下面使用Sleep 的代码会容易很多:

int count = 0;
while ( flag1 != flag2 && count < 700 )
{
   Sleep( 10 ); // wait 10ms
   ++count;
}

If you don't use Sleep (or Yield) and your app is constantly checking on a condition, then you'll bloat the CPU the app is running on.

如果您不使用 Sleep(或 Yield)并且您的应用程序不断检查条件,那么您将膨胀应用程序运行的 CPU。

If you use WinAPI extensively, you should try out a more native solution, read about WinAPI's Synchronization Functions.

如果您广泛使用 WinAPI,您应该尝试更原生的解决方案,阅读 WinAPI 的同步函数

回答by Byron Whitlock

Make sure you do a sleep()or yield()in there or you will eat up all the entire CPU (or core) waiting.

确保你在那里做一个sleep()yield(),否则你会吃掉所有等待的整个 CPU(或核心)。

回答by Arlen Beiler

I would say "check the time and if nothing has happened in seven seconds later, then break the loop.

我会说“检查时间,如果七秒后没有发生任何事情,那么打破循环。

回答by struppi

If your application does some networking stuff, have a look at the POSIX select() call, especially the timeout functionality!

如果您的应用程序执行一些网络操作,请查看 POSIX select() 调用,尤其是超时功能!