У меня есть общий ресурс, который я хочу 1 и только 1 экземпляр своего приложения (или это - API COM) иметь доступ к в любое время. Я попытался защитить этот ресурс с помощью взаимных исключений, но когда несколько потоков хоста dotnet попытка приложения получить доступ к COM-объекту, взаимное исключение, кажется, не выпущено. Это - код, я раньше защищал мой ресурс.
repeat
Mutex := CreateMutex(nil, True, PChar('Connections'));
until (Mutex <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS);
try
//use resource here!
finally
CloseHandle(Mutex);
end;
Если я выполняю потоки одновременно, первый get's потока через (очевидно, будучи первым, который создаст взаимное исключение), но последующие потоки пойманы в повторном цикле. Если я выполняю каждый поток в 5-секундных интервалах, то все в порядке.
Я подозреваю, что не использую взаимные исключения правильно здесь, но я нашел очень мало документации о том, как сделать это.
Какие-либо идеи?
Вы неправильно используете мьютекс. Вы должны дождаться этого и выпустить его, а не воссоздавать его постоянно.
Во время инициализации:
Mutex := CreateMutex(nil, False, 'Connections');
if Mutex = 0 then
RaiseLastOSError;
Если вы хотите получить доступ к ресурсу
if WaitForSingleObject(Mutex, INFINITE) <> WAIT_OBJECT_0 then
RaiseLastOSError;
try
// Use resource here
finally
ReleaseMutex(Mutex)
end;
Во время завершения
CloseHandle(Mutex);
Кроме того, поскольку мьютексы являются глобальными, вы должны выбрать что-то более уникальное, чем «соединения» для имени. Мы добавили GUID в конец нашего.
Попробуйте с помощью этого простого демонстрационного кода. Запустите несколько экземпляров приложения, и вы увидите по цвету фона, как они совместно используют мьютекс:
procedure TForm1.FormCreate(Sender: TObject);
begin
fMutex := SyncObjs.TMutex.Create(nil, False, 'GlobalUniqueName');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
fMutex.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Color := clRed;
Update;
fMutex.Acquire;
try
Color := clGreen;
Update;
Sleep(5 * 1000);
finally
fMutex.Release;
end;
Color := clBtnFace;
end;
Обратите внимание, что я решил использовать класс TMutex
из блока SyncObjs
, что упрощает работу.