• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

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

  • Автор темы Vadik(R)
  • Дата начала
V

Vadik(R)

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

Vadik(R)

Думал об этом, но проблема в том, как занести данные в очередь в нужном порядке.
Есть Someobject с событием Event.
Тогда код будет выглядеть примерно так:
Код:
//Глобальные переменные
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). А имея весь массив строк - тоже нельзя определить очередность строк. Поэтому, проблема в том, как записать в очередь строки в нужном порядке.
 
V

vitfil

Vadik®, вам же сказали: очередь. События одного уровня приоритета помещаются в очередь и не могут в ней "перемешаться".
 
V

Vadik(R)

Существует какая-либо "специальная" очередь? Не совсем понимаю тогда, о какой очереди вы говорите.
 
E

etc

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

Vadik(R)

Да, стоял :)
Но в третьем сообщении я попытался написать код с очередью, но проблема в том, что не получается избавиться от того, чтобы данные не перемешивались. Они могут добавиться в очередь не том порядке, в котором возникали события. А как правильно это реализовать - я не знаю. Я даже рисунок кое-какой набрасал, может у меня что-то неправильно в рассуждениях.

Вот, в таком случае получиться, что данные 2 вообще в очередь не попадут. Точнее, попадут, но сотруться.
А если поставить семафор в самое начало функции - то проблема исчезнет, но частично. Тогда все данные будут сохранятся в очереди, но порядок все равно не получится соблюдать, и я не знаю, как это исправить. Могу тоже иллюстрировать, как я себе это представляю. Извинюясь, что кому-то надоел, но проблема мучает очень давно и я её все время откладывал, и теперь уже хочу разобраться с ней.
 
E

etc

поищите реализацию очереди

ну и вам надо сами события в очередь ставить
 
V

Vadik(R)

1. Я не знаю, как совать события в очередь (для меня это какая-то абстрактная пока что вещь, как реализовывается - не знаю).
2. По-моему, что совать события, что обработчики в очередь - эффект будет одинаковый. Хотя я могу быть и неправым.
3. Можно ли как-нибудь узнать id обработчика? И если вообще такое существует - то делфи присваивает id'шки обработчикам (как потокам) в порядке возникновния событий?
 
V

Vadik(R)

Хм, люди. Есть вопрос, который возможно полностью решит мою проблему. Я думал в Delphi стандартные обработчики одних и тех же событий обрабатываются в разных потоках (как на рисунке в сообщении 7).
Для этой цели я решил сделать эксперимент, а именно: Установить таймер на 1 мсек и написать код:
Код:
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). Выходит, мне не о чем беспокоится?
 
V

vitfil

То есть, это говорит о том, что делфи сама во-первых, ставит события в очередь правильно, и, во-вторых, пока не завершиться обработка текущего события (onTimer), он следующее выполнять не будет. Собственно, хотел узнать у вас: действительно ли это так?
Ну а я вам о чем писал?
 
V

Vadik(R)

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

Обучение наступательной кибербезопасности в игровой форме. Начать игру!