Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.06.2008, 18:29   #11
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

mutabor,
Код:
function Check: boolean;
begin
  HM := OpenMutex(MUTEX_ALL_ACCESS, false, 'img_view_project_mutex_from_mutabor');
  Result := (HM <> 0);
  if HM = 0 then HM := CreateMutex(nil, false, 'img_view_project_mutex_from_mutabor');
end;
Та же ошибка. Суть проблемы в том, что решение принимается не на основе действительного существования мютекса, о ошибки его открытия двумя строками ранее. Под Windows нет никакой гарантии, что состояние этого мютекса не изменится за эти две строки, даже в течение одной строки. Нет даже, строго говоря, никакой гарантии, что между этими строками не пройдут месяцы или годы. В буквальном (!) смысле. Это можно очень легко увидеть в отладчике, если поставить точку, скажем, на строке "Result := (HM <> 0);" и пока программа будет ждать продолжения "отладки" - запустить её же, скомпилированую, другим процессом. После возобновления "отладки" "первая" программа запустится как вторая копия, как ни в чём не бывало. Единственное, в чём можно быть уверенным, так это в том, что состояние мютекса не изменится на протяжении одного системного вызова. Поэтому и нужно смотреть ошибку, которую возвращает именно создание объекта.

Последний раз редактировалось B_N; 18.06.2008 в 18:31.
B_N вне форума Ответить с цитированием
Старый 18.06.2008, 18:39   #12
zetrix
Delphi/C++/C#
Участник клуба
 
Аватар для zetrix
 
Регистрация: 29.10.2006
Сообщений: 1,972
По умолчанию

Ну.. Тогда объявляем эти строки как критическую секцию.
zetrix вне форума Ответить с цитированием
Старый 18.06.2008, 18:43   #13
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Цитата:
Сообщение от zetrix Посмотреть сообщение
Ну.. Тогда объявляем эти строки как критическую секцию.
А критическая секция может существовать только в рамках одного процесса. Для разных процессов это мютекс и замкнутый круг.

Ну и ведь седьмым постом я написал, как делать.
B_N вне форума Ответить с цитированием
Старый 18.06.2008, 20:15   #14
mutabor
Телепат с дипломом
Старожил
 
Аватар для mutabor
 
Регистрация: 10.06.2007
Сообщений: 4,929
По умолчанию

Цитата:
Сообщение от B_N Посмотреть сообщение
Ну и ведь седьмым постом я написал, как делать.
Да, я видел, и принял к сведению. Кто хочет может переделать. Я уже не стал менять, и так работает, и в принципе будет работать, ошибка очень маловероятна.
Кстати я читал еще может ошибка ACCESS_DENIED быть при создании, если рассматривать любую вероятность, тогда и ее нужно обработать.

Еще интересно какие есть предложения насчет хранения хэндла окна. В статье способ с реестром, я через ини сделал, но это из той же оперы. А как еще можно хранить?
The future is not a tablet with a 9" screen no more than the future was a 9" black & white screen in a box. It’s the paradigm that survives. (Kroc Camen)
Проверь себя! Онлайн тестирование | Мой блог
mutabor вне форума Ответить с цитированием
Старый 18.06.2008, 21:32   #15
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Цитата:
Сообщение от mutabor Посмотреть сообщение
Кстати я читал еще может ошибка ACCESS_DENIED быть при создании, если рассматривать любую вероятность, тогда и ее нужно обработать.
Можно, но не обязательно. Ведь объект в этом случае открыт не будет.

Цитата:
Сообщение от mutabor Посмотреть сообщение
Еще интересно какие есть предложения насчет хранения хэндла окна. В статье способ с реестром, я через ини сделал, но это из той же оперы. А как еще можно хранить?
Масса способов, на самом деле. Для обмена данными столько возможностей, что в каждом случае можно придумать что-нибудь новенькое.

Скажем, опуская тривиальную работу с WM_COPYDATA, можно сделать так:
Код:
program Project1;
uses
  Forms,
  windows,
  system,
  dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

const
    pszMutantName   : PWIDECHAR = '__$$$_TesT_lOCk_aPp_$$$__MuTaNt__';
    pszSectionName  : PWIDECHAR = '__$$$_TesT_lOCk_aPp_$$$__SeCtIoN__';


type
    SharedMem = record
        OnlyAppMainForm     : HWND;
        //.........................
    end;
var
    hMutant     : THANDLE;
    hSection    : THANDLE;
    pSharedMem  : ^SharedMem;
begin

    hMutant := CreateMutexW(nil, FALSE, pszMutantName);
    if hMutant = 0 then begin
        // Не удалось создать объект
        // Случай редкий и скорее всего говорит или о
        // неверных параметрах, или о нехватке памяти
        // Уточняется через GetLastError()
        ShowMessage('Ошибка создания объекта');
        exit;
    end
    else if GetLastError() = ERROR_ALREADY_EXISTS then begin
        // Объект уже существует, значит, с высокой вероятностью,
        // при "хорошем" имени объекта, создан другой, уже
        // работающей копией приложения

        WaitForSingleObject(hMutant, INFINITE);
// begin guarded region
        hSection := CreateFileMappingW(
                            INVALID_HANDLE_VALUE,
                            0,
                            PAGE_READONLY OR SEC_COMMIT,
                            0,
                            sizeof (SharedMem),
                            pszSectionName);
        pSharedMem := MapViewOfFile(
                            hSection,
                            FILE_MAP_READ,
                            0,
                            0,
                            0);
        if nil <> pSharedMem then begin
            PostMessage(
                    pSharedMem^.OnlyAppMainForm,
                    WM_MYMESSAGE,
                    0,
                    0);
            //....................
        end;

        UnmapViewOfFile(pSharedMem);    // 1
        CloseHandle(hSection);          // 2
// end guarded region
        ReleaseMutex(hMutant);
        CloseHandle(hMutant);           // 3

        // 1, 2 и 3 в данном случае не обязательны и сохранены
        // в целях "чистоты" кода - процесс всё равно завершается
        // и все хэндлы будут закрыты автоматически

        exit;
    end;

    Application.Initialize;
    Application.CreateForm(TForm1, Form1);

    WaitForSingleObject(hMutant, INFINITE);
// begin guarded region
    hSection := CreateFileMappingW(
                        INVALID_HANDLE_VALUE,
                        0,
                        PAGE_READWRITE OR SEC_COMMIT,
                        0,
                        sizeof (SharedMem),
                        pszSectionName);
    pSharedMem := MapViewOfFile(
                        hSection,
                        FILE_MAP_READ OR FILE_MAP_WRITE,
                        0,
                        0,
                        0);

    if nil <> pSharedMem then begin
        pSharedMem^.OnlyAppMainForm := Application.MainForm.Handle;
        //....................
    end;
// end guarded region
    ReleaseMutex(hMutant);

    Application.Run;

    UnmapViewOfFile(pSharedMem);
    CloseHandle(hSection);

end.
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

const
    WM_MYMESSAGE    = WM_USER + 100;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
    procedure OnMyMessage(var msg : TMsg); message WM_MYMESSAGE;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.OnMyMessage(var msg : TMsg);
begin
    SetForegroundWindow(self.Handle);
    windows.Beep(2000, 100);
    ShowMessage('Получено сообщение от другой копии');
end;

end.
Причем размер структуры SharedMem ограничен, фактически, только размером страничного файла, так что в неё можно записать гору общих данных.
B_N вне форума Ответить с цитированием
Старый 18.06.2008, 22:16   #16
dr.Chas
***
Участник клуба
 
Аватар для dr.Chas
 
Регистрация: 30.07.2007
Сообщений: 1,162
По умолчанию

Вот огромнейшое спасибо всем, особено mutabor, за программу, с ней на много проще будет разобраться. Завтра начну, сегодня времени нету.
dr.Chas вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как передать данные из SQL в файл _ozzy_ БД в Delphi 0 12.06.2008 16:50
Передать Канву Pedro Работа с сетью в Delphi 7 28.04.2008 17:38
Как записать данные в другую программу? Спартак Общие вопросы Delphi 23 19.04.2008 22:33
как из dll передавать данные в основную программу? andrey4623 Общие вопросы Delphi 5 06.08.2007 10:15
передать данные другому приложению vasya_pupkin Win Api 1 16.02.2007 20:17