Как Вы защищаете общий ресурс с помощью взаимных исключений?

У меня есть общий ресурс, который я хочу 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-секундных интервалах, то все в порядке.

Я подозреваю, что не использую взаимные исключения правильно здесь, но я нашел очень мало документации о том, как сделать это.

Какие-либо идеи?

6
задан Steve 18 March 2010 в 15:15
поделиться

2 ответа

Вы неправильно используете мьютекс. Вы должны дождаться этого и выпустить его, а не воссоздавать его постоянно.

Во время инициализации:

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 в конец нашего.

15
ответ дан 8 December 2019 в 04:08
поделиться

Попробуйте с помощью этого простого демонстрационного кода. Запустите несколько экземпляров приложения, и вы увидите по цвету фона, как они совместно используют мьютекс:

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, что упрощает работу.

11
ответ дан 8 December 2019 в 04:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: