Difference between revisions of "Mutex.WaitForEvents"

From SunFlurry wiki
Jump to: navigation, search
(Created page with "{{infobox function |name=WaitForEvents |object=Семафор |caption=Цикл ожидани...")
 
m (1 revision imported)
 
(No difference)

Latest revision as of 08:51, 7 February 2021

  WaitForEvents (Цикл ожидания)
Объект:Семафор
Статус разработки: Реализована
Тип:Функция
Обращение к БД:Нет
Исключения:Невозможно превратить в число, не список, неверные объекты списка, системная ошибка
Визуальность:Нет

Функция выполняет цикл ожидания для списка с событиями в течение указанного времени (по умолчанию, время не ограничено). Если одно из событий произошло (было установлено функцией SignalEvent), функция возвращает индекс этого события и автоматически сбрасывает его (и только его) состояние. Функция может быть вызвана для интерфейса Mutex. Во время исполнения цикла ожидания, обрабатываются внешние события, цикл ожидания также можно прервать из визуального клиента.

Синтаксис

Mutex.WaitForEvents(<Список событий (LIST)>,<Время ожидания в мс. (INT)>=-1):<0, если время закончилось, иначе индекс произошедшего события (INT)>

Аргументы

  • <Список событий (LIST)> - Список, содержащий объекты типа события. Функция ожидает установки по крайней мере одного события. Если событие установлено до вызова функции, функция возвратится без какого-либо ожидания.
  • <Время ожидания в мс. (INT)> - (необязательный аргумент) Задает время ожидания установки одного из событий списка, функция возвращается либо, когда одно из событий будет установлено, либо, когда истечет время ожидания. При указании -1, время ожидания не ограничено.

Возвращаемое значение

Возвращает 0, если истекло время ожидания, иначе возвращает индекс списка установленного события.

Примеры

//Пример показывает простой способ синхронизации между двумя потоками, первый поток получает внешние запросы, а второй поток обрабатывает их,
//  и передает ответ назад в первый поток, который пересылает ответ во внешний источник
//Использование событий позволяет выполнить запрос без каких либо пауз (какие появлялись бы при использовании функции Sleep внутри цикла)
//Пример использует 3 события:
//  * собВнешниеДанныеПоступили -- событие устанавливается в момент поступления внешних данных (механизм здесь не показан, он может быть любым -- событие TCP или внешнее устройство)
//  * собЗапросНаОбработку -- событие, которое устанавливает первый поток, когда он получил новые внешние данные и требуется передать их второму потоку на работку
//                            второй поток находится в ожидании этого события
//  * собДанныеОбработаны -- событие, которое устанавливает второй поток, когда он обработал данные, полученные от первого потока

//Фрагмент инициализации, происходящий до рабочего цикла
собВнешниеДанныеПоступили:=Mutex.CreateEvent();
собЗапросНаОбработку:=Mutex.CreateEvent();
собДанныеОбработаны:=Mutex.CreateEvent();

//Очереди данных и обработанных данных
спДанные:=List.Create();
спРезультат:=List.Create();
SetMultiThreaded(спДанные);
SetMultiThreaded(спРезультат);

aList:=List.Create();
aList.SetByName("ЗапросНаОбработку",собЗапросНаОбработку);
aList.SetByName("ДанныеОбработаны",собДанныеОбработаны);
aList.SetByName("Данные",спДанные);
aList.SetByName("Результат",спРезультат);
//Модуль не будет иметь формы, будет выполняться в фоне
LoadModule(0,"Modules\FreeForms\СпециальныеОбработки\ОбработчикСобытий",aList,,"Module","Form");

...

спСобытия:=List.Create(собВнешниеДанныеПоступили,собДанныеОбработаны);
//Основной цикл обработки данных
While 1 Do
  //Другая работа в цикле, проверка условия выхода из цикла и окончания работы
  ...

  //Ожидание получения или отсылки
  aNum:=Mutex.WaitForEvents(спСобытия,250);

  If aNum=1 Then
    //Поступили данные из внешнего источника, получим данные
    //Возможно здесь необходимо проверить количество данных в очереди (спДанные.Size()) и, при переполнении, отказать в получении этих данных
    аДанные:=...

    LockObject(спДанные);
    Try
      //Добавим данные в список данных, использование LockObject здесь не обязательно, однако, если кроме Add, будут использоваться
      //  другие функции для работы с спДанные, LockObject будет необходим. LockObject здесь использован для универсальности примера.
      спДанные.Add(аДанные);
    Finally
      UnlockObject(спДанные);
    EndTry;
    //Сигнал второму потоку о наличии данных
    собЗапросНаОбработку.SignalEvent();
  ElseIf aNum=2 Then
    While спРезультат.Size()>0 Do
      LockObject(спРезультат);
      Try
        //Использование LockObject здесь не обязательно, так как другой поток только добавляет данные в спРезультат в конец списка.
        //  LockObject здесь использован для универсальности примера.
        аРезультат:=спРезультат.Get(1);
        спРезультат.Remove(1);
      Finally
        UnlockObject(спРезультат);
      EndTry;
      
      //Осуществим отправку данных аРезультат
      ...
    EndDo;    
  EndIf;
EndDo;


//Данный кусок кода располагается в обработке Modules\FreeForms\СпециальныеОбработки\ОбработчикСобытий
Function OnOpen()
  Result:=0;
  If TypeStr(Param)<>"LIST" Then
    Exit;
  EndIf;
  собЗапросНаОбработку:=aList.GetByName("ЗапросНаОбработку");
  собДанныеОбработаны:=aList.GetByName("ДанныеОбработаны");
  спДанные:=aList.GetByName("Данные");
  спРезультат:=aList.GetByName("Результат");
  //Основной цикл обработки данных
  While 1 Do
    //Проверка на окончание работы
    ...
    
    If собЗапросНаОбработку.WaitForEvent(250)=1 Then
      While спДанные.Size()>0 Do
        LockObject(спДанные);
        Try
          //Использование LockObject здесь не обязательно, так как другой поток только добавляет данные в спДанные в конец списка.
          //  LockObject здесь использован для универсальности примера.
          аДанные:=спДанные.Get(1);
          спДанные.Remove(1);
        Finally
          UnlockObject(спДанные);
        EndTry;
      
        //Обработаем данные аДанные и создадим результат аРезультат
        ...

        //Добавим результат в очередь результатов
        LockObject(спРезультат);
        Try
          //Использование LockObject здесь не обязательно, так как единственная функция Add имеет свой механизм блокирования.
          //  LockObject здесь использован для универсальности примера.
          спРезультат.Add(аРезультат);
        Finally
          UnlockObject(спРезультат);
        EndTry;

        //Сообщим первому потоку, что появился новый результат
        собДанныеОбработаны.SignalEvent();
      EndDo;
    EndIf;
  EndDo;
EndFunction