C++ 用一个线程运行多个函数
我想在method1中每隔一分钟调用method2,但while循环每~1秒运行一次。我可以每1分钟从method1调用method2吗?如果是,如何?如果否,如何在不创建另一个线程的情况下每分钟调用method2?一种方法是让C++ 用一个线程运行多个函数,c++,multithreading,c++17,C++,Multithreading,C++17,我想在method1中每隔一分钟调用method2,但while循环每~1秒运行一次。我可以每1分钟从method1调用method2吗?如果是,如何?如果否,如何在不创建另一个线程的情况下每分钟调用method2?一种方法是让method1定期轮询系统,查看是否已过1分钟,例如: method1() { while(1) { some task; sleep(900); //sleep for .9 second } } method
method1
定期轮询系统,查看是否已过1分钟,例如:
method1()
{
while(1)
{
some task;
sleep(900); //sleep for .9 second
}
}
method2()
{
some task;
}
AfxBeginThread(method1, NULL);
另一种方法是让
method1
改用a,将间隔设置为1分钟,然后只要计时器已过,循环就可以调用method2
,例如:
method1()
{
auto start = ...; // GetTickCount/64(), std::chrono::steady_clock::now(), etc
while (not stopped)
{
some task;
Sleep(900); //sleep for .9 second
auto end = ...; // GetTickCount/64(), std::chrono::steady_clock::now(), etc
if ((end-start) > 60000ms)
{
method2();
start = end;
}
}
}
或者,可等待计时器支持APC回调,例如:
method1()
{
HANDLE timer = CreateWaitableTimer(NULL, FALSE, NULL);
LARGE_INTEGER DueTime;
DueTime.QuadPart = -600000000; // due in 1 minute from now
SetWaitableTimer(timer, &DueTime, 60000, NULL, NULL, FALSE); // 1 minute intervals after the DueTime passes
while (not stopped)
{
some task;
Sleep(900); //sleep for .9 second
if (WaitForSingleObject(timer, 0) == WAIT_OBJECT_0) // has timer elapsed yet?
method2();
}
CancelWaitableTimer(timer);
CloseHandle(timer);
}
在任何一种情况下,您都可以将其扩展为使用第二个可等待计时器以.9秒的间隔触发“某些任务”,然后在第一种情况下使用WaitForMultipleObjects()
循环,在第二种情况下使用第二个APC回调,例如:
void CallMethod2(LPVOID, DWORD, DWORD)
{
method2();
}
method1()
{
HANDLE timer = CreateWaitableTimer(NULL, FALSE, NULL);
LARGE_INTEGER DueTime;
DueTime.QuadPart = -600000000; // due in 1 minute from now
SetWaitableTimer(timer, &DueTime, 60000, &CallMethod2, NULL, FALSE); // 1 minute intervals after the DueTime passes
while (not stopped)
{
some task;
SleepEx(900, TRUE); //sleep for .9 second, call callback if timer elapsed
}
CancelWaitableTimer(timer);
CloseHandle(timer);
}
或者,您可以使用线程池计时器:
void PerformSomeTask(LPVOID, DWORD, DWORD)
{
some task;
}
void CallMethod2(LPVOID, DWORD, DWORD)
{
method2();
}
method1()
{
HANDLE timer1 = CreateWaitableTimer(NULL, FALSE, NULL);
HANDLE timer2 = CreateWaitableTimer(NULL, FALSE, NULL);
LARGE_INTEGER DueTime;
DueTime.QuadPart = -9000000; // due in 900ms from now
SetWaitableTimer(timer1, &DueTime, 900, &PerformSomeTask, NULL, FALSE); // .9 second intervals after the DueTime passes
DueTime.QuadPart = -600000000; // due in 1 minute from now
SetWaitableTimer(timer2, &DueTime, 60000, &CallMethod2, NULL, FALSE); // 1 minute intervals after the DueTime passes
while (not stopped)
{
SleepEx(INFINITE, TRUE); //sleep until an APC callback is called
}
CancelWaitableTimer(timer1);
CancelWaitableTimer(timer2);
CloseHandle(timer1);
CloseHandle(timer2);
}
如果您的循环大约每秒运行一次迭代,那么您在循环的每60次迭代中所做的任何事情都将大约每分钟发生一次--我 是的,但是怎么做呢拉梅什
精确性非常重要,method2每天应该准确调用1440次 那不一样。在这种情况下,您应该遵循Remy Lebeau的建议:在每次迭代中检查一天中的实际时间。如果超过了应该调用method2()的时间,则调用它,然后重新计算 我不知道C++函数的函数调用是什么。在伪代码中:
int count = 0;
while (1) {
...
if (++count >= 60) {
count = 0;
method2();
}
}
即使循环每天不执行86400次迭代,每天仍会有1440次
method2()
调用。为什么不创建另一个线程,每分钟运行method2
?需要精确到什么程度?如果您的循环大约每秒运行一次迭代,那么您在循环的每60次迭代中所做的任何事情大约每分钟都会发生一次。另外,如果您真正的意思是“调用”,请不要说“触发器”。如果method1()
中的循环调用method2(),是否满足您的要求
每分钟一次?@SolomonSlow。是的,但是怎么做呢?精度也很重要,方法2应该一天准确调用1440次。精度也很重要,方法2应该一天准确调用1440次。我会试试的,谢谢。time\u now
可能会。这将提供一个好的、可预测的单调时钟的当前时间。时钟的精度因系统而异,但秒应该足够了。这有多精确。我希望method2在一天内准确调用1440次,这取决于循环睡眠的频率。如果“某些任务”花费的时间超过1秒,则对method2的调用将不会以精确的间隔进行。如果时间很重要,请考虑在另一个线程中调用Mult2,注意里米没有使用挂钟。虽然看起来很吸引人,但使用一些简单的东西,比如时间
来给我们时间,系统时间可以改变,这真的会把每天1440次的事情搞砸。
VOID CALLBACK PerformSomeTask(PTP_CALLBACK_INSTANCE, PVOID, PTP_TIMER)
{
some task;
}
VOID CALLBACK CallMethod2(PTP_CALLBACK_INSTANCE, PVOID, PTP_TIMER)
{
method2();
}
method1()
{
PTP_TIMER timer1 = CreateThreadpoolTimer(&PerformSomeTask, NULL, NULL);
PTP_TIMER timer2 = CreateThreadpoolTimer(&CallMethod2, NULL, NULL);
ULARGE_INTEGER DueTime;
FILETIME ft;
DueTime.QuadPart = -9000000; // due in 900ms from now
ft.dwLowDateTime = DueTime.LowPart;
ft.dwHighDateTime = DueTime.HighPart;
SetThreadpoolTimer(timer1, &ft, 900, 0); // .9 second intervals after the DueTime passes
DueTime.QuadPart = -600000000; // due in 1 minute from now
ft.dwLowDateTime = DueTime.LowPart;
ft.dwHighDateTime = DueTime.HighPart;
SetThreadpoolTimer(timer2, &ft, 60000, 0); // 1 minute intervals after the DueTime passes
wait for stop condition ...
CloseThreadpoolTimer(timer1);
CloseThreadpoolTimer(timer2);
}
int count = 0;
while (1) {
...
if (++count >= 60) {
count = 0;
method2();
}
}
some_time_type_t method2_due_at = time_now() + 60_seconds;
while (1) {
...
if (time_now() > method2_due_at) {
method2();
method2_due_at += 60_seconds;
}
}