Конференция "WinAPI" » Работа с протоками
 
  • EgorovAlex (29.11.07 11:58) [0]
    При работа с потоками очень часто можно видеть такие примеры:

    procedure Test;
    begin
     CreateThread(...);
    end;



    Но здесь налицо утечка ресурсов - хендлов созданных потоков.
    Сейчас я делаю так:


    procedure Test;
    var
     hThread: Cardinal;
    begin
     hThread := CreateThread(...);
     if (hThread > 0) then
       CloseHandle(hThread);
    end;



    Теперь утечки нет, и всё нормально работает, но корректно ли закрывать хендл потока до его завершения? Если нет, тот как лучше делать?
  • guav © (29.11.07 12:01) [1]
    Закрывать действительно надо.
    Закрывать до завершения потока корректно.
    Проверять лучше hThread <> 0, а хендл объявлять как THandle.

    Лучше использовать BeginThread вместо CreateThread чтобы неявно выставлять IsMultiThread в True
  • tesseract © (29.11.07 12:05) [2]
    А смысл такой процедуры ?  

    Для того чтобы понять работает поток или нет в него передаеться Event  или их массив. При выходе потокам посылаеться соббщение "выключайся" и ждеться срабатывание WaitForMultipleObjects. Пример есть в справке delphi и MSDN.
  • EgorovAlex (29.11.07 12:12) [3]
    to tesseract:

    очень часто есть потоки, время жизни которых значительно меньше времени жизни приложения, и они создаются очень часто. Если это будет в сервисе, когда компьютер месяцами не выключается, до утечка хендлов "положит" сервер.

    to guav:
    THandle=LongWord(=Cardinal)
    а кардинал не может быть отрицательным
  • Сергей М. © (29.11.07 12:19) [4]

    > При работа с потоками очень часто можно видеть такие примеры:
    >  CreateThread(...);


    Плохие примеры.
    BeginThread следует использовать, иначе грабли рано или поздно неминуемы.
  • tesseract © (29.11.07 14:09) [5]

    > очень часто есть потоки, время жизни которых значительно
    > меньше времени жизни приложения, и они создаются очень часто.
    >


    Плохой пример. Потоки не должны создаваться и разрушаться за просто так. Использование таких "потоков" только снижает производительность, т.к. время на создание потоков затрачиваеться огромное.
  • EgorovAlex (29.11.07 14:26) [6]
    Это понятно, в таких случаях оптимальным будет пул потоков.

    Кстати может кто-нибудь объяснить, что можно делать с Queue для TThread (Delphi 2007)
  • Сергей М. © (29.11.07 14:45) [7]
    Тоже что и с любой другой очередью.
    Очередь - она и в Африке очередь)
  • EgorovAlex (29.11.07 14:48) [8]
    А для чего добавлена эта очередь? Как её использовать?
  • Сергей М. © (29.11.07 14:54) [9]
    Понятия не имею. Д2007 не пользую.

    Навскидку могу предположить, что это спецнаследник TQueue
  • tesseract © (29.11.07 15:01) [10]

    > А для чего добавлена эта очередь? Как её использовать?


    Я для D7 сам такую писал. Пишешь туда из основного потока данные, а из потоков уже их тарабанишь, из них пишешь в очередь, которая разбираеться основным потоком.
  • EgorovAlex (29.11.07 15:21) [11]
    Нет, это что-то другое. В 2007 появилось 4 новых метода, но они недокументированы:

    class procedure Queue(AThread: TThread; AMethod: TThreadMethod); overload;
    class procedure RemoveQueuedEvents(AThread: TThread; AMethod: TThreadMethod);
    class procedure StaticQueue(AThread: TThread; AMethod: TThreadMethod);
    class procedure StaticSynchronize(AThread: TThread; AMethod: TThreadMethod);
  • Сергей М. © (29.11.07 15:26) [12]

    > В 2007 появилось 4 новых метода


    Полагаю, что эти методы опираются на соответствующие нововведения в класс TThread, о коих ты почему-то не проронил ни слова.
  • EgorovAlex (29.11.07 15:36) [13]
    Вот что накопал в исходниках:


    class procedure TThread.Queue(AThread: TThread; AMethod: TThreadMethod);
    var
     LSynchronize: PSynchronizeRecord;
    begin
     if AThread <> nil then
       AThread.Queue(AMethod)
     else
     begin
       New(LSynchronize);
       try
         LSynchronize.FThread := nil;
         LSynchronize.FSynchronizeException := nil;
         LSynchronize.FMethod := AMethod;
         Synchronize(LSynchronize, True);
       finally
         if MainThreadID = GetCurrentThreadID then
           Dispose(LSynchronize);
       end;
     end;
    end;



    В ней вызывается перегруженная Synchronize(LSynchronize, True);


    class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);
    var
     SyncProc: TSyncProc;
     SyncProcPtr: PSyncProc;
    begin
     if GetCurrentThreadID = MainThreadID then
       ASyncRec.FMethod
     else
     begin
       if QueueEvent then
         New(SyncProcPtr)
       else
         SyncProcPtr := @SyncProc;
       if not QueueEvent then
         SyncProcPtr.Signal := CreateEvent(nil, True, False, nil)
       else
         SyncProcPtr.Signal := 0;
       try
        EnterCriticalSection(ThreadLock);
         try
           SyncProcPtr.Queued := QueueEvent;
           if SyncList = nil then
             SyncList := TList.Create;
           SyncProcPtr.SyncRec := ASyncRec;
           SyncList.Add(SyncProcPtr);
           SignalSyncEvent;
           if Assigned(WakeMainThread) then
             WakeMainThread(SyncProcPtr.SyncRec.FThread);
           if not QueueEvent then
           begin
             LeaveCriticalSection(ThreadLock);
             try
               WaitForSingleObject(SyncProcPtr.Signal, INFINITE);
             finally
               EnterCriticalSection(ThreadLock);
             end;
           end;
         finally
           LeaveCriticalSection(ThreadLock);
         end;
       finally
         if not QueueEvent then
           CloseHandle(SyncProcPtr.Signal);
       end;
       if not QueueEvent and Assigned(ASyncRec.FSynchronizeException) then
         raise ASyncRec.FSynchronizeException;
     end;
    end;

  • Сергей М. © (29.11.07 15:39) [14]
    Так ведь из кода все понятно)

    Разобраться-то не пытался ?
  • EgorovAlex (29.11.07 16:06) [15]
    Нет, что-то туплю :(

    Что это - очередь методов на синхронизацию?
  • Сергей М. © (29.11.07 16:27) [16]
    Из огрызка кода - да, похоже на то.
  • tesseract © (29.11.07 16:45) [17]

    > Из огрызка кода - да, похоже на то.


    Тогда  мне идея нравиться.
  • MetalFan © (01.12.07 00:12) [18]
    лучше имхо посмотреть в сторону пулов потоков...
    какойнить QueueUserWorkItem
  • Однокамушкин (02.12.07 21:35) [19]

    > EgorovAlex   (29.11.07 14:26) [6]
    > Кстати может кто-нибудь объяснить, что можно делать с Queue
    > для TThread (Delphi 2007)

    Здесь используется тот же механизм, который использует TThread.Synchronize, с одним исключением: Synchronize ставит процедуру в специальную очередь для выполнения главной нитью и ждёт, когда главная нить извлечёт её из очереди и выполнит, а Queue ставит в очередь, но ничего не ждёт: нить, вызвавшая Queue, сразу продолжает работу, а главная нить когда выполнит, тогда и выполнит... Это, если так можно выразиться, асинхронная синхронизация с главной нитью :)))
 
Конференция "WinAPI" » Работа с протоками
Есть новые Нет новых   [134435   +33][b:0][p:0.002]