2015-04-09 3 views
2

Я пишу многопоточную программу для вычисления Фибоначчи, Силы и Факториала. Вместо того, чтобы использовать Sleep, я бы хотел, чтобы потоки закончились, и я хотел бы отображать идентификаторы потоков в том порядке, в котором они заканчиваются (сначала завершено, сначала отображается). Как мне это сделать?Многопоточность WinApi C: как дождаться окончания потока?

#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

no 'WinMain()'? –

+4

['WaitForMultipleObjects'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx) в этом массиве дескрипторов будет казаться достойным делом. – WhozCraig

+1

@WeatherVane 'main' для консольных программ отлично. – deviantfan

ответ

3

@WhozCraig правильно, что вы должны использовать WaitForMultipleObjects() ждать всех потоков до конца. Прочтите this SO post для получения дополнительной информации.

Это, однако, не сообщит вам порядок, в котором они закончились, только когда все закончилось. Добавление кода в каждую функцию для печати идентификатора потока должно сделать это (используйте GetCurrentThreadId()). Например:

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

Теперь мы не должны забывать, что есть время между printf заявлением и когда нить фактически заканчивается. Вы там не занимаетесь, но технически поток все еще активен. В многопоточной среде вы не можете предсказать, сколько времени пройдет между printf и когда поток действительно завершится, независимо от того, как мало выглядит код.

Если эта разница важна для вас, вам необходимо будет присоединить каждую нить самостоятельно и посмотреть, какой из них заканчивается первым. Вы можете повторно называть WaitForSingleObject() на каждом дескрипторе потока с нулевым таймаутом и определять, какой из них завершается первым. Да, есть небольшое состояние гонки, если третий поток немного заканчивается перед вторым, пока вы проверяете первый, а затем проверяете второй поток и замечаете, что он завершен. Вы упустите тот факт, что третий финишировал первым. И этот метод опроса меняет эксперимент, потребляя много процессорного времени, пока он ждет.

Лично я считаю, что вам лучше просто записать время (основанное на системных часах), когда каждый поток завершил вычисление своего результата, а не когда его поток завершен. Используйте GetTickCount() или QueryPerformanceCounter() для измерения времени.

Смежные вопросы