我不知道如何准确地搜索这个..所以我没有任何运气找到任何东西..:S
我需要在 C 中实现时间延迟。
例如,我想做一些事情,然后等 1 分钟,然后继续做事情。
这有意义吗?谁能帮我吗?
在标准 C (C99) 中,您可以使用它time()
来执行此操作,例如:
#include <time.h>
:
void waitFor (unsigned int secs) {
unsigned int retTime = time(0) + secs; // Get finishing time.
while (time(0) < retTime); // Loop until it arrives.
}
顺便说一句,这假设time()
返回一个 1 秒的分辨率值。我不认为这是标准规定的,因此您可能需要对其进行调整。
为了澄清,这是我知道使用 ISO C99 执行此操作的唯一方法(并且问题仅用“C”标记,这通常意味着便携式解决方案是可取的,当然,供应商特定的解决方案仍可给予)。
无论如何,如果您在一个提供更有效方式的平台上,请使用它。正如一些评论所指出的那样,在 CPU 使用率和电池寿命方面,像这样的紧密循环可能存在特定问题。
任何体面的时间片操作系统都可以降低连续使用其完整时间片的任务的动态优先级,但电池电量可能会更成问题。
但是 C没有指定托管环境中的操作系统细节,这个答案仅适用于 ISO C 和 ISO C(因此不使用sleep
, select
, Win32 API 调用或类似的东西)。
请记住,POSIXsleep
可能会被信号中断。如果您打算走这条路,您需要执行以下操作:
int finishing = 0; // set finishing in signal handler
// if you want to really stop.
void sleepWrapper (unsigned int secs) {
unsigned int left = secs;
while ((left > 0) && (!finishing)) // Don't continue if signal has
left = sleep (left); // indicated exit needed.
}
以下是在大多数桌面系统上执行此操作的方法:
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
void wait( int seconds )
{ // Pretty crossplatform, both ALL POSIX compliant systems AND Windows
#ifdef _WIN32
Sleep( 1000 * seconds );
#else
sleep( seconds );
#endif
}
int
main( int argc, char **argv)
{
int running = 3;
while( running )
{ // do something
--running;
wait( 3 );
}
return 0; // OK
}
以下是在没有计时器的微型计算机/处理器上执行此操作的方法:
int wait_loop0 = 10000;
int wait_loop1 = 6000;
// for microprocessor without timer, if it has a timer refer to vendor documentation and use it instead.
void
wait( int seconds )
{ // this function needs to be finetuned for the specific microprocessor
int i, j, k;
for(i = 0; i < seconds; i++)
{
for(j = 0; j < wait_loop0; j++)
{
for(k = 0; k < wait_loop1; k++)
{ // waste function, volatile makes sure it is not being optimized out by compiler
int volatile t = 120 * j * i + k;
t = t + 5;
}
}
}
}
int
main( int argc, char **argv)
{
int running = 3;
while( running )
{ // do something
--running;
wait( 3 );
}
return 0; // OK
}
waitloop 变量必须进行微调,这些对我的计算机来说确实非常接近,但是频率尺度的东西对于现代桌面系统来说非常不精确;所以不要在那里使用,除非你对金属不敏感并且不做这些事情。
尽管许多实现都具有以秒time
为单位返回当前时间的函数,但不能保证每个实现都会这样做(例如,有些实现可能返回毫秒而不是秒)。因此,更便携的解决方案是使用该功能。difftime
difftime
C 标准保证返回两个值之间的时间差(以秒为单位)。time_t
因此,我们可以编写一个可移植的时间延迟函数,它将在所有符合C 标准的实现上运行。
#include <time.h>
void delay(double dly){
/* save start time */
const time_t start = time(NULL);
time_t current;
do{
/* get current time */
time(¤t);
/* break loop when the requested number of seconds have elapsed */
}while(difftime(current, start) < dly);
}
time
和difftime
函数的一个警告是C 标准从不指定粒度。大多数实现的粒度为一秒。虽然这对于持续几秒钟的延迟来说是可以的,但我们的延迟功能可能会因为延迟持续不到一秒而等待太久。
有一个可移植的标准 C 替代方案:clock
函数。
clock
自仅与程序调用相关的实现定义时代开始以来,该函数返回实现对程序使用的处理器时间的最佳近似值。要确定以秒为单位的时间,clock
函数返回的值应除以宏的值CLOCKS_PER_SEC
。
函数解决方案与我们的函数解决clock
方案非常相似time
:
#include <time.h>
void delay(double dly){
/* save start clock tick */
const clock_t start = clock();
clock_t current;
do{
/* get current clock tick */
current = clock();
/* break loop when the requested number of seconds have elapsed */
}while((double)(current-start)/CLOCKS_PER_SEC < dly);
}
在这种情况下,有一个类似于time
and的警告difftime
:函数的粒度clock
留给实现。例如,具有 32 位值clock_t
且分辨率以微秒为单位的机器可能最终会clock
在 2147 秒(约 36 分钟)后包装返回的值。
因此,请考虑对持续至少一秒的延迟使用延迟函数的time
和实现,以及持续一秒以下的延迟的实现。difftime
clock
最后要注意的是:clock
返回处理器时间而不是日历时间;clock
可能与实际经过的时间不对应(例如,如果进程休眠)。
对于长达一分钟的延迟,sleep()
是一个不错的选择。
如果有一天,您想暂停小于一秒的延迟,您可能需要考虑poll()
超时。
两者都是POSIX。
尝试sleep(int number_of_seconds)
sleep(int)
作为一个很好的延迟。一分钟:
//Doing some stuff...
sleep(60); //Freeze for A minute
//Continue doing stuff...
C11 之前的 C 标准库中没有sleep()
函数,但 POSIX 确实提供了一些选项。
POSIX 函数sleep()
(unistd.h) 需要一个unsigned int
参数来表示希望休眠的秒数。虽然这不是标准库函数,但它可以广泛使用,而且 glibc 似乎支持它,即使在使用更严格的设置(如--std=c11
.
POSIX 函数nanosleep()
(time.h) 将两个指向timespec
结构的指针作为参数,并提供对睡眠持续时间的更精细控制。第一个参数指定延迟持续时间。如果第二个参数不是空指针,则它保存调用被信号处理程序中断时的剩余时间。
使用该nanosleep()
功能的程序可能需要包含功能测试宏才能编译。当我使用典型的编译器调用gcc -std=c11 -Wall -Wextra -Wpedantic
.
POSIX 曾经有一个usleep()
函数 (unistd.h),它接受一个useconds_t
参数来指定以微秒为单位的睡眠持续时间。当与严格的编译器设置一起使用时,此函数还需要一个功能测试宏。唉,usleep()
在 POSIX.1-2001 中已过时,不应再使用。建议nanosleep()
现在使用而不是usleep()
.
#define _POSIX_C_SOURCE 199309L // feature test macro for nanosleep()
#include <stdio.h>
#include <unistd.h> // for sleep()
#include <time.h> // for nanosleep()
int main(void)
{
// use unsigned sleep(unsigned seconds)
puts("Wait 5 sec...");
sleep(5);
// use int nanosleep(const struct timespec *req, struct timespec *rem);
puts("Wait 2.5 sec...");
struct timespec ts = { .tv_sec = 2, // seconds to wait
.tv_nsec = 5e8 }; // additional nanoseconds
nanosleep(&ts, NULL);
puts("Bye");
return 0;
}
C11 确实有threads.h
提供的标头thrd_sleep()
,其工作方式与nanosleep()
. GCCthreads.h
直到 2018 年才支持glibc 2.28。通常很难找到支持的实现threads.h
(Clang 很长一段时间都不支持它,但我不确定那里的当前状态)。您必须小心使用此选项。
是timer
吗?
对于 WIN32 尝试http://msdn.microsoft.com/en-us/library/ms687012%28VS.85%29.aspx
你可以简单地调用 delay() 函数。因此,如果您想在 3 秒内延迟该过程,请调用 delay(3000)...
如果您确定要等待并且永远不会被打断,请在 POSIX 中使用 sleep 或在 Windows 中使用 Sleep。在 POSIX 中,睡眠需要以秒为单位的时间,因此如果您希望时间更短,可以usleep()
使用微秒等多种类型。Windows 中的睡眠需要几毫秒,很少需要比这更精细的粒度。
您可能希望等待一段时间,但希望允许中断,可能是在紧急情况下。睡眠可以被信号中断,但在这种情况下有更好的方法。
因此,我实际上在实践中发现您所做的是等待事件或条件变量超时。
在 Windows 中,您的呼叫是WaitForSingleObject
. 在 POSIX 中是pthread_cond_timedwait
.
在 Windows 中,您也可以使用WaitForSingleObjectEx
,然后您实际上可以通过调用QueueUserAPC
. WaitForSingleObject(Ex) 将返回一个确定它退出原因的代码,因此您将知道它何时返回“TIMEDOUT”状态它确实超时。当您希望它终止时,您可以设置它正在等待的事件。
你可以用pthread_cond_timedwait
信号广播条件变量。(如果多个线程在同一个线程上等待,则需要广播以唤醒它们)。每次循环时,它都应该检查条件。您的线程可以获取当前时间并查看它是否已经过去,或者它可以查看是否满足某些条件以确定要做什么。如果你有某种队列,你可以检查一下。(您的线程将自动锁定一个用于等待条件变量的互斥锁,因此当它检查条件时,它可以单独访问它)。
// 提供延迟 x 毫秒的 ANSI C 方法
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void delayMillis(unsigned long ms) {
clock_t start_ticks = clock();
unsigned long millis_ticks = CLOCKS_PER_SEC/1000;
while (clock()-start_ticks < ms*millis_ticks) {
}
}
/*
* Example output:
*
* CLOCKS_PER_SEC:[1000000]
*
* Test Delay of 800 ms....
*
* start[2054], end[802058],
* elapsedSec:[0.802058]
*/
int testDelayMillis() {
printf("CLOCKS_PER_SEC:[%lu]\n\n", CLOCKS_PER_SEC);
clock_t start_t, end_t;
start_t = clock();
printf("Test Delay of 800 ms....\n", CLOCKS_PER_SEC);
delayMillis(800);
end_t = clock();
double elapsedSec = end_t/(double)CLOCKS_PER_SEC;
printf("\nstart[%lu], end[%lu], \nelapsedSec:[%f]\n", start_t, end_t, elapsedSec);
}
int main() {
testDelayMillis();
}
C11 有一个专门用于此的功能:
#include <threads.h>
#include <time.h>
#include <stdio.h>
void sleep(time_t seconds) {
struct timespec time;
time.tv_sec = seconds;
time.tv_nsec = 0;
while (thrd_sleep(&time, &time)) {}
}
int main() {
puts("Sleeping for 5 seconds...");
sleep(5);
puts("Done!");
return 0;
}
请注意,这仅从 glibc 2.28 开始可用。
用于 gcc 中的 C 语言。#include <windows.h>
然后使用睡眠();/// Sleep() 大写 S。不是 sleep() 和 s 。
//Sleep(1000) 是 1 秒 /// 也许。
clang 支持 sleep(),sleep(1) 是 1 秒时间延迟/等待。
您使用什么操作系统?
我知道在 Windows 上,您可以执行以下操作:
//include crap
#include <windows.h>
int main () {
//do things
Sleep(/* ur wait time in ms */);// wait for param1 ms
//continue to do things
}
对于 Linux 操作系统上的短暂延迟(例如,几微秒),您可以使用“usleep”:
// C Program to perform short delays
#include <unistd.h>
#include <stdio.h>
int main(){
printf("Hello!\n");
usleep(1000000); // For a 1-second delay
printf("Bye!\n);
return 0;
system("timeout /t 60"); // waits 60s. this is only for windows vista,7,8
system("ping -n 60 127.0.0.1 >nul"); // waits 60s. for all windows
写下这段代码:
void delay(int x)
{ int i=0,j=0;
for(i=0;i<x;i++){for(j=0;j<200000;j++){}}
}
int main()
{
int i,num;
while(1) {
delay(500);
printf("Host name");
printf("\n");}
}