![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
WaitForSingleObject не ожидает закрытия мютекста
DelphiN! © (2007-06-19 13:05:00)Пишу:
var
MHandle: THandle;
function Test: Boolean;
begin
MHandle := CreateMutex(nil,false,'MyTest0000001');
if WaitForSingleObject(MHandle,INFINITE) = 0 then
Result := false//Error
else
Result := true; //TimeOut
end;
И всегда мгновенно получаю в Result false
Почему так происходит??
DelphiN! (2007-06-20 11:54:00) [1]Спасибо, буду разбираться!
clickmaker (2007-06-20 10:55:00) [2]
> [22] DelphiN! © (20.06.07 10:13)
никак. Они не по этим делам
если очень хочется таймаут, можно юзать TEvent или CreateEvent()
ага (2007-06-20 10:54:00) [3]А никак. Можно только использовать TryEnterCriticalSection
DelphiN! (2007-06-20 10:13:00) [4]А как объекту класса TCriticalSection назначить тайм аут?
DelphiN! (2007-06-20 10:13:00) [5]А как обекту класса TCriticalSection назначить тайм аут?
ага (2007-06-20 09:53:00) [6]а у вас каждый поток создаёт свой собственный мьютекс и захватывает его, поэтому никакой синхронизации нет вообще
Есть синхронизация. У него мьетекс именованный. А зывисает на Wait потому, что поток где-то блокируется, может диадлок. И критические секции сами собой это не устранят.
DelphiN! (2007-06-20 09:37:00) [7]
> Однокамушкин (20.06.07 08:58) [18]
Спасибо! С критическими секциями и проще и в моем случае без сбоев! :)
Однокамушкин (2007-06-20 08:58:00) [8]
> DelphiN! © (19.06.07 19:05) [17]
> В проекте много потоковых функций, обезопасил всех их следующим
> образом :
Не обезопасили... чтобы потоки синхронизировались, они все должны использовать один и тот же мьютекс, а у вас каждый поток создаёт свой собственный мьютекс и захватывает его, поэтому никакой синхронизации нет вообще... смотрите Сергей М. © (19.06.07 14:12) [14] - не зря Сергей сделал переменную h глобальной, а вот CreateMutex перед WaitForSingleObject поставил зря, мьютекс должен создаваться один раз и потом использоваться везде...
И в вашем случае вообще лучше пользоваться не мьютексами, а критическими секциями - они работвают быстрее... Преимущества мьютекса перед критической секцией заключаются в том, что мьютекс, во-первых, можно использовать для синхронизации потоков разных процессов, а критические секции - только одного, а во-вторых, мьютекс, в отличие от критической секции, может быть включен в список объектов синхронизации, ожидаемых совместно функцией WaitForMultipleObjects, а критическая секция всегда ожидается независимо... Но в вашем коде нет ни того, ни другого, так что пользуйтесь критической секцией...
DelphiN! (2007-06-19 19:05:00) [9]В проекте много потоковых функций, обезопасил всех их следующим образом :
function TDATA.GetHTTPParams(HTTPPost: String): String;
var
...
begin
try
//Lock thread
GetHTTPParamsH := CreateMutex(nil,true,'GetHttpParams');
WaitForSingleObject(GetHttpParamsH,INFINITE);
...
finally
ReleaseMutex(GetHTTPParamsH);
CloseHandle(GetHTTPParamsH);
end;
end;
Создаю потоки в событии OnGetThread компонента TServerSocket следующим образом :
procedure TMain.ServerSocketGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread := TServerThread.Create(false, ClientSocket);
end;
procedure TServerThread.ClientExecute;
var
...
begin
...
s := GetHTTPParams(HTTPPost);
...
end;
Но иногда поток зависает на WaitForSingleObject(GetHttpParamsH,INFINITE)
Это происходит если потоки создаются очень интенсивно, например если зажать обновление страницы на клиенте и серверу приходит очень много запросов.
С чем это может быть связано и как этого можно избежать?
Однокамушкин (2007-06-19 15:26:00) [10]
> DelphiN! © (19.06.07 14:02) [13]
> Получается что вот эта процедура будет защищенной от одновременного
> доступа нескольких потоков?
Только в том случае, если они тоже пытаются захватить этот же мьютекс, прежде чем обращаться к совместно используемуму ресурсу...
DelphiN! (2007-06-19 14:36:00) [11]
> Сергей М. © (19.06.07 14:12) [14]
Спасибо огромное!
Сергей М. (2007-06-19 14:12:00) [12]var
h: Handle;
function a(Data: Pointer): Integer; stdcall;
var
i,j: Integer;
begin
h := CreateMutex(nil,true,'MyMutex');
WaitForSingleObject(h,INFINITE);
//здесь преспокойно обращаешься к защищенному ресурсу
ReleaseMutex(h);
end;
var
i: Integer;
c: Cardinal;
begin
for i := 0 to 100 do
CreateThread(nil,0,@a,nil,0,c);
end.
DelphiN! (2007-06-19 14:02:00) [13]Получается что вот эта процедура будет защищенной от одновременного доступа нескольких потоков?
var
h: Handle;
procedure a;
var
i,j: Integer;
begin
WaitForSingleObject(h,INFINITE);
h := CreateMutex(nil,true,'MyMutex');
for i := 0 to 100 do
for j := 0 to 100 do
s := s+1;
ReleaseMutex(h);
end;
var
i: Integer;
c: Cardinal;
begin
for i := 0 to 100 do
CreateThread(nil,0,@a,nil,0,c);
end.
Однокамушкин (2007-06-19 13:56:00) [14]
> DelphiN! © (19.06.07 13:22) [5]
> Но ведь ф-ия WaitForSingleObject должна замораживать поток
> до тех пор, пока указатель MHandle существует, либо не был
> превышен тайм аут?
Нет, она затормаживает поток до тех пор, пока объект синхронизации находится в сигнализированном состоянии, а созданный вами мьютекс по умолчанию не в сигнализированном...
А вообще, вы, видимо, путаете с использованием WaitForSingleObject для ожидания окончания работы процесса или потока... но и там всё не так - сам поток или нить уже могут завершить работу, а объект будет продолжать существовать, если есть открытые хэндлы... просто такие объекты находятся в сигнализированном состоянии до тех пор, пока поток или процесс работают, а после их завершения переходят в несигнализированное, продолжая, тем не менее, существовать...
Anatoly Podgoretsky (2007-06-19 13:49:00) [15]> Сергей М. (19.06.2007 13:47:09) [9]
Это будет уже второй ответ, пока критичен первый
clickmaker (2007-06-19 13:49:00) [16]
> [5] DelphiN! © (19.06.07 13:22)
ну вот пример использования
Процесс 1
hMutex := CreateMutex(nil, true, 'Mutex1'); // завладели мьютексом
// критический код
ReleaseMutex(hMutex); // отдали мьютекс
CloseHandle(hmutex);
Процесс 2
hMutex := OpenMutex(READ_CONTROL or SYNCHRONIZE, False, 'Mutex1');
// ждем, пока Процесс 1 завершит крит. код
WaitForSingleObject(hMutext, INFINITE); // или таймаут в мс
CloseHandle(hMutex);
Сергей М. (2007-06-19 13:47:00) [17]
> Anatoly Podgoretsky © (19.06.07 13:39) [8]
Ну это само собой.
Можно и разрешить - все равно выхода по таймауту не будет.
Anatoly Podgoretsky (2007-06-19 13:39:00) [18]> Сергей М. (19.06.2007 13:33:07) [7]
Таймаута не будет по другой причине, поскольку он запрещен.
Сергей М. (2007-06-19 13:33:00) [19]
> вместо тайм аута я получаю в результате функии 0 и ее мгновенное
> завершение
Да какой еще там таймаут ты ждешь ?
Не будет никакого таймаута, потому что мьютекс на момент вызова ф-ции ожидания гарантированно существует и им не владеет ни один из потоков.
Вызвав ф-цию ты тут же стал владельцем мьютекса, о чем тебя и известил нулевой рез-т вызова ф-ции.
Anatoly Podgoretsky (2007-06-19 13:28:00) [20]Таймаут? Шутишь?