![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с протоками
EgorovAlex © (2007-11-29 11:58:00)При работа с потоками очень часто можно видеть такие примеры:
procedure Test;
begin
CreateThread(...);
end;
Но здесь налицо утечка ресурсов - хендлов созданных потоков.
Сейчас я делаю так:
procedure Test;
var
hThread: Cardinal;
begin
hThread := CreateThread(...);
if (hThread > 0) then
CloseHandle(hThread);
end;
Теперь утечки нет, и всё нормально работает, но корректно ли закрывать хендл потока до его завершения? Если нет, тот как лучше делать?
Игорь Шевченко (2008-07-21 15:20:00) [1]
> При работа с потоками очень часто можно видеть такие примеры:
>
>
> procedure Test;
> begin
> CreateThread(...);
> end;
Ну наверное этот код не для сервиса, работающего месяцами. Но вполне допустимый для ряда задач, например таких, где время жизни приложения немногим превышает время работы потока.
Германн (2008-07-19 01:00:00) [2]<offtop>
> GrayFace © (19.07.08 00:55) [21]
>
> В коде из превого поста еще не хватает вызовов Win32Check.
> А если без них, то я бы написал CloseHandle(CreateThread(.
> ..));
>
Оп ля. Как влияет недавно прошедший день рождения на человека!
Некромант, однако :)
(с) sniknik
GrayFace (2008-07-19 00:55:00) [3]В коде из превого поста еще не хватает вызовов Win32Check. А если без них, то я бы написал CloseHandle(CreateThread(...));
EgorovAlex (2007-12-02 22:06:00) [4]to Однокамушкин:
Спасибо, я тоже к такому выводу пришёл
Однокамушкин (2007-12-02 21:35:00) [5]
> EgorovAlex (29.11.07 14:26) [6]
> Кстати может кто-нибудь объяснить, что можно делать с Queue
> для TThread (Delphi 2007)
Здесь используется тот же механизм, который использует TThread.Synchronize, с одним исключением: Synchronize ставит процедуру в специальную очередь для выполнения главной нитью и ждёт, когда главная нить извлечёт её из очереди и выполнит, а Queue ставит в очередь, но ничего не ждёт: нить, вызвавшая Queue, сразу продолжает работу, а главная нить когда выполнит, тогда и выполнит... Это, если так можно выразиться, асинхронная синхронизация с главной нитью :)))
MetalFan (2007-12-01 00:12:00) [6]лучше имхо посмотреть в сторону пулов потоков...
какойнить QueueUserWorkItem
tesseract (2007-11-29 16:45:00) [7]
> Из огрызка кода - да, похоже на то.
Тогда мне идея нравиться.
Сергей М. (2007-11-29 16:27:00) [8]Из огрызка кода - да, похоже на то.
EgorovAlex (2007-11-29 16:06:00) [9]Нет, что-то туплю :(
Что это - очередь методов на синхронизацию?
Сергей М. (2007-11-29 15:39:00) [10]Так ведь из кода все понятно)
Разобраться-то не пытался ?
EgorovAlex (2007-11-29 15:36:00) [11]Вот что накопал в исходниках:
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:26:00) [12]
> В 2007 появилось 4 новых метода
Полагаю, что эти методы опираются на соответствующие нововведения в класс TThread, о коих ты почему-то не проронил ни слова.
EgorovAlex (2007-11-29 15:21:00) [13]Нет, это что-то другое. В 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);
tesseract (2007-11-29 15:01:00) [14]
> А для чего добавлена эта очередь? Как её использовать?
Я для D7 сам такую писал. Пишешь туда из основного потока данные, а из потоков уже их тарабанишь, из них пишешь в очередь, которая разбираеться основным потоком.
Сергей М. (2007-11-29 14:54:00) [15]Понятия не имею. Д2007 не пользую.
Навскидку могу предположить, что это спецнаследник TQueue
EgorovAlex (2007-11-29 14:48:00) [16]А для чего добавлена эта очередь? Как её использовать?
Сергей М. (2007-11-29 14:45:00) [17]Тоже что и с любой другой очередью.
Очередь - она и в Африке очередь)
EgorovAlex (2007-11-29 14:26:00) [18]Это понятно, в таких случаях оптимальным будет пул потоков.
Кстати может кто-нибудь объяснить, что можно делать с Queue для TThread (Delphi 2007)
tesseract (2007-11-29 14:09:00) [19]
> очень часто есть потоки, время жизни которых значительно
> меньше времени жизни приложения, и они создаются очень часто.
>
Плохой пример. Потоки не должны создаваться и разрушаться за просто так. Использование таких "потоков" только снижает производительность, т.к. время на создание потоков затрачиваеться огромное.
Сергей М. (2007-11-29 12:19:00) [20]
> При работа с потоками очень часто можно видеть такие примеры:
> CreateThread(...);
Плохие примеры.
BeginThread следует использовать, иначе грабли рано или поздно неминуемы.