WinApi C多线程:如何等待线程完成?

时间:2015-04-09 20:18:35

标签: c multithreading winapi

我正在编写一个多线程程序来计算Fibonacci,Power和Factorial。而不是使用Sleep,我想等待线程完成,并且我想按照它们完成的顺序显示线程的ID(首先完成,首先显示)。我该怎么做?

    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

unsigned int n = 0;
int priorytety[3] = { THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL};
HANDLE watki[3];

DWORD WINAPI Fibbonaci(void *argumenty){
    unsigned long long int prevPrev = 0;
    unsigned long long int prev = 1;
    unsigned long long int wynik = 1;
    while (wynik <= n){
        wynik = prev + prevPrev;
        prevPrev = prev;
        prev = wynik;
    }
    printf("fibbonaci : %llu \n", wynik);
    ExitThread(wynik);
    //return wynik;
}

DWORD WINAPI Potegi(void *argumenty){
    unsigned long long int wynik = 2;
    while (wynik <= n){
        wynik = wynik << 1;
    }
    printf("potegi : %llu \n", wynik);
    return wynik;
}

DWORD WINAPI Silnia(void *argumenty){
    //printf("%d", atoi(argv[argc-1]));
    unsigned long long int wynik = 1;
    unsigned long long int i = 1;
    while (wynik <= n){
        wynik = wynik * i;
        i = i + 1;
    }
    printf("silnia : %llu \n", wynik);
    return wynik;
}


int main(){
    int i;
    DWORD id;
    system("cls");
    scanf_s("%d", &n);
    LPTHREAD_START_ROUTINE WINAPI funkcje[3] = { Fibbonaci, Potegi, Silnia };
    for (i = 0; i < 3; i++)
    {
        watki[i] = CreateThread(
            NULL, // atrybuty bezpieczeństwa
            10000, // inicjalna wielkość stosu
            funkcje[i] , // funkcja wątku
            (void *)n,// dane dla funkcji wątku
            0, // flagi utworzenia
            &id);
        if (watki[i] != INVALID_HANDLE_VALUE)
        {
            //printf("Utworzylem watek o identyfikatorze %x\n", id);
            // ustawienie priorytetu
            SetThreadPriority(watki[i], priorytety[1]);
        }
    }
    Sleep(10000);
    getchar();
}

1 个答案:

答案 0 :(得分:3)

@WhozCraig是正确的,您应该使用WaitForMultipleObjects()等待所有线程完成。请阅读this SO post以获取更多信息。

然而,只有当所有人都完成时,它才会告诉你他们结束的顺序。向每个函数添加代码以打印其线程ID应该这样做(使用GetCurrentThreadId())。例如:

printf("potegi : %llu, thread ID %ld \n", wynik, GetCurrentThreadId());

现在我们不要忘记printf语句和线程实际完成之间有时间。你没有在那里做任何工作,但从技术上讲,线程仍然是活跃的。在多线程环境中,无法预测printf与线程真正终止之间的时间间隔,无论代码有多少。

如果这种差异对您很重要,那么您需要独立加入每个线程并查看哪个线程首先终止。您可以使用零超时重复调用每个线程句柄上的WaitForSingleObject(),并检测哪个首先终止。是的,如果第三个线程在第二个线程之前稍微完成,而您在检查第一个线程时,则存在轻微的竞争条件,然后检查第二个线程并注意它已终止。你会错过第三个完成的事实。这种轮询技术通过在等待时消耗大量CPU来改变实验。

就我个人而言,我认为你最好只记录每个线程完成计算结果的时间(基于系统时钟),而不是在线程终止时。使用GetTickCount()QueryPerformanceCounter()来衡量时间。