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