-
При работа с потоками очень часто можно видеть такие примеры:
procedure Test;
begin
CreateThread(...);
end;
Но здесь налицо утечка ресурсов - хендлов созданных потоков. Сейчас я делаю так:
procedure Test;
var
hThread: Cardinal;
begin
hThread := CreateThread(...);
if (hThread > 0) then
CloseHandle(hThread);
end;
Теперь утечки нет, и всё нормально работает, но корректно ли закрывать хендл потока до его завершения? Если нет, тот как лучше делать?
-
Закрывать действительно надо. Закрывать до завершения потока корректно. Проверять лучше hThread <> 0, а хендл объявлять как THandle.
Лучше использовать BeginThread вместо CreateThread чтобы неявно выставлять IsMultiThread в True
-
А смысл такой процедуры ?
Для того чтобы понять работает поток или нет в него передаеться Event или их массив. При выходе потокам посылаеться соббщение "выключайся" и ждеться срабатывание WaitForMultipleObjects. Пример есть в справке delphi и MSDN.
-
to tesseract:
очень часто есть потоки, время жизни которых значительно меньше времени жизни приложения, и они создаются очень часто. Если это будет в сервисе, когда компьютер месяцами не выключается, до утечка хендлов "положит" сервер.
to guav: THandle=LongWord(=Cardinal) а кардинал не может быть отрицательным
-
> При работа с потоками очень часто можно видеть такие примеры: > CreateThread(...);
Плохие примеры. BeginThread следует использовать, иначе грабли рано или поздно неминуемы.
-
> очень часто есть потоки, время жизни которых значительно > меньше времени жизни приложения, и они создаются очень часто. >
Плохой пример. Потоки не должны создаваться и разрушаться за просто так. Использование таких "потоков" только снижает производительность, т.к. время на создание потоков затрачиваеться огромное.
-
Это понятно, в таких случаях оптимальным будет пул потоков.
Кстати может кто-нибудь объяснить, что можно делать с Queue для TThread (Delphi 2007)
-
Тоже что и с любой другой очередью. Очередь - она и в Африке очередь)
-
А для чего добавлена эта очередь? Как её использовать?
-
Понятия не имею. Д2007 не пользую.
Навскидку могу предположить, что это спецнаследник TQueue
-
> А для чего добавлена эта очередь? Как её использовать?
Я для D7 сам такую писал. Пишешь туда из основного потока данные, а из потоков уже их тарабанишь, из них пишешь в очередь, которая разбираеться основным потоком.
-
Нет, это что-то другое. В 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 появилось 4 новых метода
Полагаю, что эти методы опираются на соответствующие нововведения в класс TThread, о коих ты почему-то не проронил ни слова.
-
Вот что накопал в исходниках:
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;
-
Так ведь из кода все понятно)
Разобраться-то не пытался ?
-
Нет, что-то туплю :(
Что это - очередь методов на синхронизацию?
-
Из огрызка кода - да, похоже на то.
-
> Из огрызка кода - да, похоже на то.
Тогда мне идея нравиться.
-
лучше имхо посмотреть в сторону пулов потоков... какойнить QueueUserWorkItem
-
> EgorovAlex (29.11.07 14:26) [6] > Кстати может кто-нибудь объяснить, что можно делать с Queue > для TThread (Delphi 2007)
Здесь используется тот же механизм, который использует TThread.Synchronize, с одним исключением: Synchronize ставит процедуру в специальную очередь для выполнения главной нитью и ждёт, когда главная нить извлечёт её из очереди и выполнит, а Queue ставит в очередь, но ничего не ждёт: нить, вызвавшая Queue, сразу продолжает работу, а главная нить когда выполнит, тогда и выполнит... Это, если так можно выразиться, асинхронная синхронизация с главной нитью :)))
|