c - WinApi C 多线程 : how to wait for a thread to finish?

标签 c multithreading winapi

我正在编写一个多线程程序来计算斐波那契数、幂数和阶乘。我不想使用 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();
}

最佳答案

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

但是,只有当所有任务都完成时,它才会告诉您它们结束的顺序。向每个函数添加代码以打印其线程 ID 应该可以做到这一点(使用 GetCurrentThreadId() )。例如:

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

现在我们不能忘记,在 printf 语句和线程实际完成之间存在时间。您没有在那里做任何工作,但从技术上讲,该线程仍然处于事件状态。在多线程环境中,无论代码看起来有多么少,您都无法预测 printf 与线程真正终止之间会经过多少时间。

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

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

关于c - WinApi C 多线程 : how to wait for a thread to finish?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29548164/

相关文章:

c - 瓦尔格林 |大小为 8 的无效读取 |地址 0x7a41270 在大小为 4 的 block 内是 0 个字节,已分配

c - 从单链表打印结构数据

c - 两个长数相乘

c - 打印结构体的值不显示正确的值

java - 我应该如何处理 AI 线程和主游戏循环之间的通信?

c# - 检测鼠标的后退/前进按钮是否被按下

iphone - 并发和非并发 NSOperations 队列问题

python - 用于对抗 "Not Responding"阻塞的多处理 GUI 模式

c++ - 未定义对 `TextOutA@20' 的引用

visual-studio - 如何从 windbg/dbgeng api 获取部分信息/偏移权限?