Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.09.06;
Скачать: CL | DM;

Вниз

Работа с протоками   Найти похожие ветки 

 
EgorovAlex   (2007-11-29 11:58) [0]

При работа с потоками очень часто можно видеть такие примеры:

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


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


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


Теперь утечки нет, и всё нормально работает, но корректно ли закрывать хендл потока до его завершения? Если нет, тот как лучше делать?


 
guav ©   (2007-11-29 12:01) [1]

Закрывать действительно надо.
Закрывать до завершения потока корректно.
Проверять лучше hThread <> 0, а хендл объявлять как THandle.

Лучше использовать BeginThread вместо CreateThread чтобы неявно выставлять IsMultiThread в True


 
tesseract ©   (2007-11-29 12:05) [2]

А смысл такой процедуры ?  

Для того чтобы понять работает поток или нет в него передаеться Event  или их массив. При выходе потокам посылаеться соббщение "выключайся" и ждеться срабатывание WaitForMultipleObjects. Пример есть в справке delphi и MSDN.


 
EgorovAlex   (2007-11-29 12:12) [3]

to tesseract:

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

to guav:
THandle=LongWord(=Cardinal)
а кардинал не может быть отрицательным


 
Сергей М. ©   (2007-11-29 12:19) [4]


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


Плохие примеры.
BeginThread следует использовать, иначе грабли рано или поздно неминуемы.


 
tesseract ©   (2007-11-29 14:09) [5]


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


Плохой пример. Потоки не должны создаваться и разрушаться за просто так. Использование таких "потоков" только снижает производительность, т.к. время на создание потоков затрачиваеться огромное.


 
EgorovAlex   (2007-11-29 14:26) [6]

Это понятно, в таких случаях оптимальным будет пул потоков.

Кстати может кто-нибудь объяснить, что можно делать с Queue для TThread (Delphi 2007)


 
Сергей М. ©   (2007-11-29 14:45) [7]

Тоже что и с любой другой очередью.
Очередь - она и в Африке очередь)


 
EgorovAlex   (2007-11-29 14:48) [8]

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


 
Сергей М. ©   (2007-11-29 14:54) [9]

Понятия не имею. Д2007 не пользую.

Навскидку могу предположить, что это спецнаследник TQueue


 
tesseract ©   (2007-11-29 15:01) [10]


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


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


 
EgorovAlex   (2007-11-29 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);


 
Сергей М. ©   (2007-11-29 15:26) [12]


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


Полагаю, что эти методы опираются на соответствующие нововведения в класс TThread, о коих ты почему-то не проронил ни слова.


 
EgorovAlex   (2007-11-29 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;


 
Сергей М. ©   (2007-11-29 15:39) [14]

Так ведь из кода все понятно)

Разобраться-то не пытался ?


 
EgorovAlex   (2007-11-29 16:06) [15]

Нет, что-то туплю :(

Что это - очередь методов на синхронизацию?


 
Сергей М. ©   (2007-11-29 16:27) [16]

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


 
tesseract ©   (2007-11-29 16:45) [17]


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


Тогда  мне идея нравиться.


 
MetalFan ©   (2007-12-01 00:12) [18]

лучше имхо посмотреть в сторону пулов потоков...
какойнить QueueUserWorkItem


 
Однокамушкин   (2007-12-02 21:35) [19]


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

Здесь используется тот же механизм, который использует TThread.Synchronize, с одним исключением: Synchronize ставит процедуру в специальную очередь для выполнения главной нитью и ждёт, когда главная нить извлечёт её из очереди и выполнит, а Queue ставит в очередь, но ничего не ждёт: нить, вызвавшая Queue, сразу продолжает работу, а главная нить когда выполнит, тогда и выполнит... Это, если так можно выразиться, асинхронная синхронизация с главной нитью :)))


 
EgorovAlex   (2007-12-02 22:06) [20]

to Однокамушкин:

Спасибо, я тоже к такому выводу пришёл


 
GrayFace ©   (2008-07-19 00:55) [21]

В коде из превого поста еще не хватает вызовов Win32Check. А если без них, то я бы написал CloseHandle(CreateThread(...));


 
Германн ©   (2008-07-19 01:00) [22]

<offtop>

> GrayFace ©   (19.07.08 00:55) [21]
>
> В коде из превого поста еще не хватает вызовов Win32Check.
>  А если без них, то я бы написал CloseHandle(CreateThread(.
> ..));
>

Оп ля. Как влияет недавно прошедший день рождения на человека!
Некромант, однако :)
(с) sniknik


 
Игорь Шевченко ©   (2008-07-21 15:20) [23]


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


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



Страницы: 1 вся ветка

Текущий архив: 2009.09.06;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.014 c
15-1246739521
Юрий
2009-07-05 00:32
2009.09.06
С днем рождения ! 5 июля 2009 воскресенье


15-1246882901
inventor_delirium
2009-07-06 16:21
2009.09.06
Использование процессора другого компьютера, как своего..


15-1246725022
KilkennyCat
2009-07-04 20:30
2009.09.06
Линукс. Скрипт удаления файла.


2-1246964960
rassl
2009-07-07 15:09
2009.09.06
Классы форм


15-1246536336
@!!ex
2009-07-02 16:05
2009.09.06
Сторожа сторожат хозяев