1. Акция на весь декабрь! Получай оплату х2 за уникальные статьи, объемом от 200 слов, если в заголовке темы и теле статьи присутствует слово Python
    Скрыть объявление

Последовательная обработка событий

Тема в разделе "Delphi - FAQ", создана пользователем Vadik(R), 5 ноя 2010.

  1. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Люди, помогите с проблемой. Допустим есть какое-то событие Event, которое происходит с неизвестным интервалом времени, и есть обработчик этого события - OnEvent. В который передаются данные, например, строка. Вопрос в следующем: событие может возникать очень часто и обработчик события, возможно, будет неуспевать обрабатывать переданные ему данные, как тут же запустится обработчик второго события. По идее, предотвратить это легко, например, семафором. То есть, тогда обработчик следующего события не запустится, пока не завершиться текущий. Но есть еще проблемка: нужно, чтобы события обрабатывались в той последовательности, в которой они появлялись. То есть, произошли собития Event с данными Data1, Event с данными Data2 и Event с данными Data3. Если использовать семафор, то вначале будет обрабатываться событие Event с данными Data1, а остальные будут ждать семафора. Но когда его обработка закончится, с равной вероятностью может выполняться как обработчик события Event с данными Data2, так и обработчик события Event с данными Data3. Нужно, чтобы они делались последовательно в том порядке, в котором они возникали. То есть, шла обработка вначале Event с данными Data1, потом Event с данными Data2 и потом Event с данными Data3. Помогите, как этого добиться?
     
  2. etc

    etc Гость

    Очередь.
     
  3. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Думал об этом, но проблема в том, как занести данные в очередь в нужном порядке.
    Есть Someobject с событием Event.
    Тогда код будет выглядеть примерно так:
    Код (Text):
    //Глобальные переменные
    var
    queue: array [1..1000] of ansistring;
    n1, n2: integer;

    procedure SomeobjectEvent(str: ansistring);
    begin
    inc(n2);
    queue[n2] := str;
    ...{семефор}
    inc(n1);
    ... {Обработка строки queue[n1]}
    end;
    И вот тут и проявляется этот минус. Поскольку, строка с индексом n1 - не обязательно та, которая должна обрабатываться (могло получиться так queue[1] = str1, queue[2] = str3, queue[3] = str2). А имея весь массив строк - тоже нельзя определить очередность строк. Поэтому, проблема в том, как записать в очередь строки в нужном порядке.
     
  4. vitfil

    vitfil IT-интегратор

    Регистрация:
    2 апр 2004
    Сообщения:
    2.070
    Симпатии:
    0
    Vadik®, вам же сказали: очередь. События одного уровня приоритета помещаются в очередь и не могут в ней "перемешаться".
     
  5. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Существует какая-либо "специальная" очередь? Не совсем понимаю тогда, о какой очереди вы говорите.
     
  6. etc

    etc Гость

    Очередь это "первый пришел - первый ушел", в магазине в очереди стояли? тут оно тоже самое.
     
  7. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Да, стоял :)
    Но в третьем сообщении я попытался написать код с очередью, но проблема в том, что не получается избавиться от того, чтобы данные не перемешивались. Они могут добавиться в очередь не том порядке, в котором возникали события. А как правильно это реализовать - я не знаю. Я даже рисунок кое-какой набрасал, может у меня что-то неправильно в рассуждениях.
    http://s011.radikal.ru/i315/1011/6d/71e6a15a0117.jpg
    Вот, в таком случае получиться, что данные 2 вообще в очередь не попадут. Точнее, попадут, но сотруться.
    А если поставить семафор в самое начало функции - то проблема исчезнет, но частично. Тогда все данные будут сохранятся в очереди, но порядок все равно не получится соблюдать, и я не знаю, как это исправить. Могу тоже иллюстрировать, как я себе это представляю. Извинюясь, что кому-то надоел, но проблема мучает очень давно и я её все время откладывал, и теперь уже хочу разобраться с ней.
     
  8. etc

    etc Гость

  9. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    1. Я не знаю, как совать события в очередь (для меня это какая-то абстрактная пока что вещь, как реализовывается - не знаю).
    2. По-моему, что совать события, что обработчики в очередь - эффект будет одинаковый. Хотя я могу быть и неправым.
    3. Можно ли как-нибудь узнать id обработчика? И если вообще такое существует - то делфи присваивает id'шки обработчикам (как потокам) в порядке возникновния событий?
     
  10. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Хм, люди. Есть вопрос, который возможно полностью решит мою проблему. Я думал в Delphi стандартные обработчики одних и тех же событий обрабатываются в разных потоках (как на рисунке в сообщении 7).
    Для этой цели я решил сделать эксперимент, а именно: Установить таймер на 1 мсек и написать код:
    Код (Text):
    unit Unit1;

    interface

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

    type
    TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;
    n: integer;

    implementation

    {$R *.dfm}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    n := 0;
    Timer1.Enabled := True;
    end;

    procedure TForm1.Timer1Timer(Sender: TObject);
    var
    f: textfile;
    begin
    if n > 100000 then Timer1.Enabled := False;
    inc(n);
    assignfile(f, '1.txt');
    append(f);
    writeln(f, n);
    closefile(f);
    end;

    end.
    И, по идее, если обработчики выполняются в разных потоках - успела бы возникнуть ошибка, что есть попытка открыть файл, который открыт уже другим обработчиком. На 100000 событий уж наверняка бы появилась ошибка. Но каково же было моё удивление, когда я открыл файл и увидел в нём _последовательно_ идущие числа. То есть, это говорит о том, что делфи сама во-первых, ставит события в очередь правильно, и, во-вторых, пока не завершиться обработка текущего события (onTimer), он следующее выполнять не будет. Собственно, хотел узнать у вас: действительно ли это так?
    И справедливо ли это для обработчика procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);??
    Просто я в обработчике делаю довольно долгую обработку полученной строки O(n^2) и пишу её в файл. Я не боялся, что будет двойное открытие файла для записи, эту проблему я знал как уладить. Я боялся, что запись в файл будет происходит не в том порядке, в котором приходит текст (могла прийти длинная, а потом короткая строка) (рассуждения из рисунка сообщения 7). Выходит, мне не о чем беспокоится?
     
  11. vitfil

    vitfil IT-интегратор

    Регистрация:
    2 апр 2004
    Сообщения:
    2.070
    Симпатии:
    0
    Ну а я вам о чем писал?
     
  12. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Ааа, да я не знал об этом, я думал самому это реализовывать как-то надо, а Delphi - по-моему мнению обрабатывала события в случайном порядке. Тогда остался еще небольшой вопрос - Application.ProcessMessages - обрабатывает следующее в очереди событие или следующии события?
     
Загрузка...

Поделиться этой страницей