C++ 用一个线程运行多个函数

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中每隔一分钟调用method2,但while循环每~1秒运行一次。我可以每1分钟从method1调用method2吗?如果是,如何?如果否,如何在不创建另一个线程的情况下每分钟调用method2?

一种方法是让
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;
    }
}