Форум: "Начинающим";
Текущий архив: 2007.07.15;
Скачать: [xml.tar.bz2];
ВнизWaitForSingleObject не ожидает закрытия мютекста Найти похожие ветки
← →
DelphiN! © (2007-06-19 13:05) [0]Пишу:
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
Почему так происходит??
← →
clickmaker © (2007-06-19 13:11) [1]а какой смысл создавать мьютекс с bInitialOwner = False и тут же приниматься ждать его? в том же процессе/потоке, причем
← →
Игорь Шевченко © (2007-06-19 13:12) [2]
>
> И всегда мгновенно получаю в Result false
> Почему так происходит??
Ты получаешь, что Mutex для твоего процесса доступен. Это тебя удивляет ?
← →
Сергей М. © (2007-06-19 13:15) [3]
> всегда мгновенно получаю в Result false
> Почему так происходит??
>
Потому что мьютекс успешно занят тек.потоком при вызове тобой ф-ции WaitForSingleObject
← →
Сергей М. © (2007-06-19 13:16) [4]
> Result := false //Error
Чтой-то вдруг error ?
В чем ты видишь ошибку при этом ?
← →
DelphiN! © (2007-06-19 13:22) [5]
> clickmaker © (19.06.07 13:11) [1]
Я просто хочу проверить как ф-ия WaitForSingleObject ожидает закрытия мьютекста, тоесть я хочу получить от нее тайм аут в данном случае, просто для проверки, но тайм аут я не получаю!
> Игорь Шевченко © (19.06.07 13:12) [2]
Но ведь ф-ия WaitForSingleObject должна замораживать поток до тех пор, пока указатель MHandle существует, либо не был превышен тайм аут? Тоесть в моем случае я должен получить через некоторое время тайм аут, так как я не закрываю указатель MHandle, но вместо тайм аута я получаю в результате функии 0 и ее мгновенное завершение!
← →
Anatoly Podgoretsky © (2007-06-19 13:28) [6]Таймаут? Шутишь?
← →
Сергей М. © (2007-06-19 13:33) [7]
> вместо тайм аута я получаю в результате функии 0 и ее мгновенное
> завершение
Да какой еще там таймаут ты ждешь ?
Не будет никакого таймаута, потому что мьютекс на момент вызова ф-ции ожидания гарантированно существует и им не владеет ни один из потоков.
Вызвав ф-цию ты тут же стал владельцем мьютекса, о чем тебя и известил нулевой рез-т вызова ф-ции.
← →
Anatoly Podgoretsky © (2007-06-19 13:39) [8]> Сергей М. (19.06.2007 13:33:07) [7]
Таймаута не будет по другой причине, поскольку он запрещен.
← →
Сергей М. © (2007-06-19 13:47) [9]
> Anatoly Podgoretsky © (19.06.07 13:39) [8]
Ну это само собой.
Можно и разрешить - все равно выхода по таймауту не будет.
← →
clickmaker © (2007-06-19 13:49) [10]
> [5] DelphiN! © (19.06.07 13:22)
ну вот пример использования
Процесс 1hMutex := CreateMutex(nil, true, "Mutex1"); // завладели мьютексом
// критический код
ReleaseMutex(hMutex); // отдали мьютекс
CloseHandle(hmutex);
Процесс 2hMutex := OpenMutex(READ_CONTROL or SYNCHRONIZE, False, "Mutex1");
// ждем, пока Процесс 1 завершит крит. код
WaitForSingleObject(hMutext, INFINITE); // или таймаут в мс
CloseHandle(hMutex);
← →
Anatoly Podgoretsky © (2007-06-19 13:49) [11]> Сергей М. (19.06.2007 13:47:09) [9]
Это будет уже второй ответ, пока критичен первый
← →
Однокамушкин (2007-06-19 13:56) [12]
> DelphiN! © (19.06.07 13:22) [5]
> Но ведь ф-ия WaitForSingleObject должна замораживать поток
> до тех пор, пока указатель MHandle существует, либо не был
> превышен тайм аут?
Нет, она затормаживает поток до тех пор, пока объект синхронизации находится в сигнализированном состоянии, а созданный вами мьютекс по умолчанию не в сигнализированном...
А вообще, вы, видимо, путаете с использованием WaitForSingleObject для ожидания окончания работы процесса или потока... но и там всё не так - сам поток или нить уже могут завершить работу, а объект будет продолжать существовать, если есть открытые хэндлы... просто такие объекты находятся в сигнализированном состоянии до тех пор, пока поток или процесс работают, а после их завершения переходят в несигнализированное, продолжая, тем не менее, существовать...
← →
DelphiN! © (2007-06-19 14:02) [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 14:12) [14]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:36) [15]
> Сергей М. © (19.06.07 14:12) [14]
Спасибо огромное!
← →
Однокамушкин (2007-06-19 15:26) [16]
> DelphiN! © (19.06.07 14:02) [13]
> Получается что вот эта процедура будет защищенной от одновременного
> доступа нескольких потоков?
Только в том случае, если они тоже пытаются захватить этот же мьютекс, прежде чем обращаться к совместно используемуму ресурсу...
← →
DelphiN! © (2007-06-19 19:05) [17]В проекте много потоковых функций, обезопасил всех их следующим образом :
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-20 08:58) [18]
> DelphiN! © (19.06.07 19:05) [17]
> В проекте много потоковых функций, обезопасил всех их следующим
> образом :
Не обезопасили... чтобы потоки синхронизировались, они все должны использовать один и тот же мьютекс, а у вас каждый поток создаёт свой собственный мьютекс и захватывает его, поэтому никакой синхронизации нет вообще... смотрите Сергей М. © (19.06.07 14:12) [14] - не зря Сергей сделал переменную h глобальной, а вот CreateMutex перед WaitForSingleObject поставил зря, мьютекс должен создаваться один раз и потом использоваться везде...
И в вашем случае вообще лучше пользоваться не мьютексами, а критическими секциями - они работвают быстрее... Преимущества мьютекса перед критической секцией заключаются в том, что мьютекс, во-первых, можно использовать для синхронизации потоков разных процессов, а критические секции - только одного, а во-вторых, мьютекс, в отличие от критической секции, может быть включен в список объектов синхронизации, ожидаемых совместно функцией WaitForMultipleObjects, а критическая секция всегда ожидается независимо... Но в вашем коде нет ни того, ни другого, так что пользуйтесь критической секцией...
← →
DelphiN! © (2007-06-20 09:37) [19]
> Однокамушкин (20.06.07 08:58) [18]
Спасибо! С критическими секциями и проще и в моем случае без сбоев! :)
← →
ага (2007-06-20 09:53) [20]а у вас каждый поток создаёт свой собственный мьютекс и захватывает его, поэтому никакой синхронизации нет вообще
Есть синхронизация. У него мьетекс именованный. А зывисает на Wait потому, что поток где-то блокируется, может диадлок. И критические секции сами собой это не устранят.
← →
DelphiN! © (2007-06-20 10:13) [21]А как обекту класса TCriticalSection назначить тайм аут?
← →
DelphiN! © (2007-06-20 10:13) [22]А как объекту класса TCriticalSection назначить тайм аут?
← →
ага (2007-06-20 10:54) [23]А никак. Можно только использовать TryEnterCriticalSection
← →
clickmaker © (2007-06-20 10:55) [24]
> [22] DelphiN! © (20.06.07 10:13)
никак. Они не по этим делам
если очень хочется таймаут, можно юзать TEvent или CreateEvent()
← →
DelphiN! © (2007-06-20 11:54) [25]Спасибо, буду разбираться!
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.07.15;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.053 c