简体   繁体   中英

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

Windows 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.

Any help is appreciated. Thanks.

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.

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

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.

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

 }

You can use QueryPerformanceCounter from 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).

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

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.

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

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 WaitForSingleObject function with a 7000 millisecond time out.

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM