Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
 Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Delphi-приложение может быть запущенно в нескольких экземлярах.
Например, запущено три.
Хочу решить такую задачу - мне нужно отреагировать в момент, когда пользователь закрывает два экземляра, и остается только один (последний).
Посоветуйте, в какую сторону копать? Хочется что-то вроде сабжа.

Сообщение было отредактировано: 31 май 21, 11:33
31 май 21, 11:41    [22329207]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32387

семафоры

Posted via ActualForum NNTP Server 1.5

31 май 21, 11:56    [22329222]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53435

Квейд
Посоветуйте, в какую сторону копать?

MMF из свапа. Это даст тебе общую память, где ты можешь держать атомарный счётчик или
чёрта с рогами.

Posted via ActualForum NNTP Server 1.5

31 май 21, 12:34    [22329256]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3862
семафоры, у них есть счетчик, глобальные на всю систему.
31 май 21, 23:54    [22329612]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53435

makhaon
семафоры, у них есть счетчик, глобальные на всю систему

У них совсем плохо с сигнализацией достижения единицы. Да и с нулём не очень.

Posted via ActualForum NNTP Server 1.5

1 июн 21, 00:33    [22329619]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
Квейд,

а у MMF плохо с завершением - выпала программа, а твой счётчик не обновился.
1 июн 21, 11:20    [22329725]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
ziv-2014
Member

Откуда:
Сообщений: 599
Квейд,
OpenThread и WaitForObject. В каждой копии программы открываешь главный поток и ждешь его завершения. Как главный поток завершился, уменьшаешь счетчик. Таким образом каждая копия программы мониторит друг друга.
1 июн 21, 11:32    [22329732]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 755
Надо именно ловить момент, когда экземпляр остается в одиночестве? Чтобы из реплики стать мастером? Может, event поможет? В мастере создается, реплики мониторят. Как только мастер закрывается, реплика создает event и становится мастером
1 июн 21, 11:38    [22329739]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53435

kealon(Ruslan)
выпала программа, а твой счётчик не обновился.

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

Posted via ActualForum NNTP Server 1.5

1 июн 21, 13:27    [22329805]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
ziv-2014
Member

Откуда:
Сообщений: 599
Dimitry Sibiryakov,
Пользователь прибил приложение и все счетчик не обновился.
1 июн 21, 14:47    [22329859]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53435

При обычном прибитии приложению сначала посылается штатный WM_CLOSE. Чтобы счётчик не
обновился приложение должно либо зависнуть, либо прибитие нужно жёсткое, с
TerminateProcess, каковое для обычных пользователей слишком сложно, ибо делается с
"нипанятной" страница таскменеджера.

Ну и последующие глюки - тоже на его, пользователя, совести.

Posted via ActualForum NNTP Server 1.5

1 июн 21, 14:53    [22329868]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
Dimitry Sibiryakov

Ну и последующие глюки - тоже на его, пользователя, совести.

Приложение которое не защищено от нештатного завершения - это кривые руки программиста.

Сообщение было отредактировано: 1 июн 21, 16:22
1 июн 21, 16:31    [22329934]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 755
А цель-то какая?
1 июн 21, 16:42    [22329940]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
Dimitry Sibiryakov

kealon(Ruslan)
выпала программа, а твой счётчик не обновился.

Поэтому нормальные программисты стараются писать программы, которые не выпадают.
стараться и написать - разные вещи, а вот спустить ответственность на пользователя - это непроффесионализм
1 июн 21, 19:01    [22330037]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
Электричество закончилось - тоже проблема пользователя?
1 июн 21, 19:36    [22330051]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1834
YuRock
Электричество закончилось - тоже проблема пользователя?

Тогда счетчик уже не важен :)
1 июн 21, 19:40    [22330052]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
У меня идея такая, как вариант.
1. Пытаемся создать серверный сокет на определенный порт.
2. Если получилось - ты единственная (главная) программа.
3. Если не получилось - пытаемся подключиться к такому серверу. Подключились, и начинаем вечно чего-то ждать от сервера. Как придет ошибка (сервер закрылся) - возвращаемся в п. 1.
На локальных сокетах должно всё мгновенно отрабатывать по идее, даже если жОстко снять процесс сервера.
1 июн 21, 19:42    [22330054]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
X-Cite
YuRock
Электричество закончилось - тоже проблема пользователя?

Тогда счетчик уже не важен :)
А, ну да))
1 июн 21, 19:43    [22330055]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
GunSmoker
Member

Откуда:
Сообщений: 3231
1. Первый запущенный экземпляр открывает MMF и становится "главным".
2. Все последующие - проверяют MMF и регистрируют в главном экземпляре себя (например, отправкой сообщений в окно, указанное в MMF). Хэндл на MMF не держат открытым.
3. Главный экземпляр ждёт завершения всех зарегистрированных вторичных процессов.
4. Если главный процесс закрывается пользователем раньше вторичных - нужно себя отфинализировать полностью, но MMF не закрывать, ждать завершения всех вторичных, а потом грохнуться.
5. Событие "остается только один (последний) экземпляр" наступает, когда главный процесс дожидается завершения всех зарегистрированных вторичных. В этом случае последний экземпляр - главный. Либо, если главный уже логически финализирован, то когда он дождётся завершения всех, кроме одного вторичного. В этом случае последний экземпляр - оставшийся вторичный.

В качестве главного процесса можно использовать вспомогательный exe, чтобы не было необходимости закрывать его раньше вторичных.

Если вторичный процесс терминируется - главный об этом узнает. Если терминируется главный - ой. Как вариант: вторичные процессы тоже могут ждать завершения главного, и если он закрылся раньше вторичного - переизбрать главного среди вторичных (например, кто первее переоткроет MMF - того и тапки).
1 июн 21, 20:45    [22330067]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
GunSmoker,

А если тупо создать два глобальных Mutex'a причём один захватывает первый запущенный экземпляр приложения, а следующий - отпускает. После чего все экземпляры приложения в отдельном потоке ждут на этих Mutex'ах. И если у какого-то экземпляра они оказываются оба, то он проверяет наличие других экземпляров (неважно как) и если не находит - профит. Ну и снова отпускает один Mutex. Только при запуске нового экземпляра надо сообщить об этом всем остальным, чтобы они начали ждать.

Сообщение было отредактировано: 1 июн 21, 21:00
1 июн 21, 21:07    [22330083]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
GunSmoker

В качестве главного процесса можно использовать вспомогательный exe, чтобы не было необходимости закрывать его раньше вторичных.
а рабочие процессы, как вариант, запускать в job-е
там много что можно настроить
1 июн 21, 22:12    [22330111]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
+ Уголок извращенца
unit loMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FMutex: array [0..1] of THandle;
    FEvent: THandle;
    FThread: TThread;
  public
    procedure WaitSingleInstance;
    procedure DoSingleInstance;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DoSingleInstance;
begin
  ShowMessage('Single Instance!');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FEvent := CreateEvent(nil, True, False, nil);
  FMutex[0] := CreateMutex(nil, False, 'TLO_A');
  FMutex[1] := CreateMutex(nil, False, 'TLO_B');
  WaitSingleInstance;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  ThreadHandle: Thandle;
begin
  ThreadHandle := FThread.Handle;
  SetEvent(FEvent); //Killing thread
  WaitForSingleObject(ThreadHandle, INFINITE);
  CloseHandle(FEvent);
  { !!! Не закрываем хэндлы мьютексов! }
end;

procedure TForm1.WaitSingleInstance;
begin
  FThread := TThread.CreateAnonymousThread(

    procedure
    var
      IsSingleInstance: Boolean;
      hObjects: array of THandle;
    begin
      IsSingleInstance := True;
      hObjects := [FMutex[0], FMutex[1], FEvent];

      { Ждём получения первого мьютекса }
      case WaitForMultipleObjects(3, @hObjects[0], False, INFINITE) of

        WAIT_OBJECT_0,
        WAIT_ABANDONED_0:
          hObjects := [FMutex[1], FEvent];

        WAIT_OBJECT_0 + 1,
        WAIT_ABANDONED_0 + 1:
          hObjects := [FMutex[0], FEvent];

      else
        Exit;
      end;

      while WaitForSingleObject(FEvent, 0) = WAIT_TIMEOUT do
      begin

        { Ждём получения второго мьютекса }
        case WaitForMultipleObjects(2, @hObjects[0], False, 100) of

          WAIT_OBJECT_0,
          WAIT_ABANDONED_0:
            begin
              ReleaseMutex(hObjects[0]);
              if IsSingleInstance then
              begin
                Sleep(100);
                Continue;
              end;
            end;

          WAIT_TIMEOUT:
            begin
              IsSingleInstance := False;
              Continue;
            end

        else
          Exit;
        end;

        { Проверяем - перехватил ли кто-нибудь мьютекс? }
        if WaitForSingleObject(hObjects[0], 0) = WAIT_OBJECT_0 then
        begin
          IsSingleInstance := True;
          ReleaseMutex(hObjects[0]);
          TThread.Synchronize(nil, DoSingleInstance);
        end;

      end;
    end);

  FThread.Start;
end;

end.


Сообщение было отредактировано: 2 июн 21, 02:10
2 июн 21, 02:17    [22330137]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Каждый процесс создаёт в заведомо известном каталоге временный файл (флаг FILE_FLAG_DELETE_ON_CLOSE) и подписывается на изменения содержимого каталога.
Всё. Телемаркет.
2 июн 21, 12:06    [22330245]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65920
Блог
Квейд
Посоветуйте, в какую сторону копать? Хочется что-то вроде сабжа.

Лично я, во-первых, посмотрел бы алгоритмы выбора мастера (ведущего из кучи равноправных нод итп), а во-вторых, намонстрячил бы небольшой протокол на RegisterWindowMessage/HWND_BROADCAST. Что-нибудь типа того:

а) сдыхающий мастер делает рассылку о выборах
б) каждый получивший отвечает рассылкой свежесгенерированного guid-а, выдавший наименьший считает себя мастером
в) усомнившийся в существовании других опять же делает рассылку о выборах (на случай тихо сдохшего мастера)
2 июн 21, 12:28    [22330254]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6743
А вот если организовать что-то такое:

1) простенькой COM-объект
2) и пусть каждое приложение создаёт себе его экземпляр
3) у COM-объекта пусть будет событие (не знаю, возможно такое), связанное с изменением числа инстансов и обработчик этого события и есть искомая фишка
2 июн 21, 13:12    [22330281]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
Все форумы / Delphi Ответить