delphi многопоточность

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by realcoder, 13 Mar 2011.

  1. realcoder

    realcoder Member

    Joined:
    9 Dec 2010
    Messages:
    226
    Likes Received:
    11
    Reputations:
    4
    как заставить программу ждать завершения потока?
    если я пишу:
    Code:
    Program prog;
    var  i:integer;
      thr,id:array [1..300] of Cardinal;
    
    Procedure proc;
    begin
    MessageBox(0,'Yo!','',mb_ok);
    end;
    
    begin
    for i := 1 to 300 do
      begin
        thr[i]:=CreateThread(nil,0,@proc,nil,0,id[i]);
      end;
    end.
    
    сообщения появляются, тутже исчезают и прога отсатавливается.
    если вот так:
    Code:
    Program prog;
    var  i:integer;
      thr,id:array [1..300] of Cardinal;
    
    Procedure proc;
    begin
    MessageBox(0,'Yo!','',mb_ok);
    end;
    
    begin
    for i := 1 to 300 do
      begin
        thr[i]:=CreateThread(nil,0,@proc,nil,0,id[i]);
      end;
    sleep(5000);
    end.
    
    сообщения появляются на 5 сек и прога завершается.
    вопрос как заставить прогу ждать завершения потоков?
     
  2. k0tt0d

    k0tt0d Member

    Joined:
    19 Nov 2009
    Messages:
    49
    Likes Received:
    20
    Reputations:
    4
    ставишь счетчик, при завершении каждого потока увеличиваешь его на единицу, в основном потоке ждешь, когда этот счетчик будет равен числу потоков. Не забыть про синхронизацию, примерно так
    Code:
    Program prog;
    
    var  i:integer;
         thr,id:array [1..300] of Cardinal;
         fl:integer;//счетчик для контроля завершения потоков
         cs:TRTLCriticalSection ;//крит секция
    
    Procedure proc;
    begin
    MessageBox(0,'Yo!','',mb_ok);
    EnterCriticalSection(cs);
    inc(fl);
    LeaveCriticalSection(cs);
    end;
    
    begin
    InitializeCriticalSection(cs);
    
    for i := 1 to 300 do
      begin
        thr[i]:=CreateThread(nil,0,@proc,nil,0,id[i]);
      end;
    
    fl:=0;
    repeat
    sleep(10);
    until fl=length(thr);
    
    end.
     
    1 person likes this.
  3. ЕгоАкк

    ЕгоАкк Banned

    Joined:
    21 Sep 2009
    Messages:
    84
    Likes Received:
    18
    Reputations:
    0
    for (i = 0; i < threadsnum; i++)
    WaitForSingleObject(threads, INFINITE);

    WaitForMultipleObjects не может принять более 64 объектов.
     
    2 people like this.
  4. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Псевдокодом можно это описать так:
    Code:
    var N - глобальная переменная
    // наша функция которая что-то делает там
    function THProc (p:pointer):dword;stdcall;
    begin
     трам парам
     //  при завершении работы потока атомарно уменьшим кол-во активных потоков
     InterlockedDecriment( N );
    end;
    
    N := 0; // пока у нас 0 активных потоков
    
    for x :=  to Z do // цикл запуска Z потоков
    begin
     h := CreateThread(**** THProc ***) // запускаем поток
     if (h <> 0) then // если запустился
     begin
        CloseHandle(h); // закрываем хендл потока чтобы не мешался
         InterlockedIncriment(  N ); // атомарно увеличиваем кол-во активных потоков
     end;
    end;
    
     // гоняем цикл пока есть активные потоки
    while (N <> 0) do
    begin
     Sleep(100);  // делаем паузу 1/10 секунду чтобы проц не подвешивался
    end;
     
    
    Код такой будет работать идеально и пофигу сколько потоков будет использоваться
     
    1 person likes this.
  5. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    И так:)
    Code:
    var N : Integer; глобальная переменная
    var event : THande;
    // наша функция которая что-то делает там
    function THProc (p:pointer):dword;stdcall;
    begin
        трам парам
        //  при завершении работы потока атомарно уменьшим кол-во активных потоков
        if InterlockedDecriment( N ) = 0 then
          SetEvent(event);
    end;
    
    ...
    
    event := CreateEvent(nil, true, false, nil);
    N := 0; // пока у нас 0 активных потоков
    
    for x := 1 to Z do // цикл запуска Z потоков
    begin
     h := BeginThread(nil, 0, @THProc, nil, CREATE_SUSPENDED, dummy); //запускаем поток
     if (h <> 0) then // если запустился
     begin
        InterlockedIncriment(  N ); // атомарно увеличиваем кол-во активных потоков
        ResumeThread(h);
        CloseHandle(h); // закрываем хендл потока чтобы не мешался
     end;
    end;
      // гоняем цикл пока есть активные потоки
      if WaitForSingleObject(event, INFINITE) <> WAIT_ABANDONED then
        CloseHandle(event);
    
     
    1 person likes this.
  6. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    k0tt0d в общем правильно но использовать крит. секции для чисел это жесть :)
     
  7. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    Лолват? "Для чисел лучше забыть про interlocked" - типа я вот так вот писал?
    "еще и на генериках..." и? дженерики медленные чтоли? вроде тут ошибочное представление о природе дженериков..это же не variant, и не TValue и не любой другой "универсальный тип" а именно дженерики.