Mutex.CreateEvent

From SunFlurry wiki
Jump to: navigation, search
  CreateEvent (Создать семафор)
Объект:Семафор
Статус разработки: Реализована
Тип:Функция
Обращение к БД:Нет
Исключения:Невозможно превратить в число, системная ошибка
Визуальность:Нет

Функция создает новое системное событие с возможным указанием его начального состояния. Событие может принимать два состояния: установлено и сброшено, и может использоваться при вызове функций WaitForEvent или WaitForEvents.

Синтаксис

Mutex.CreateEvent(<Начальное состояние (INT)>=0):<Новый объект события (MUTEX)>

Аргументы

  • <Начальное состояние (INT)> - (необязательный аргумент) Задает начальное состояние системного события: 0 (по умолчанию) -- сброшено, 1 -- установлено.

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

Возвращает новый объект события.

Примеры

//Пример показывает простой способ синхронизации между двумя потоками, первый поток получает внешние запросы, а второй поток обрабатывает их,
//  и передает ответ назад в первый поток, который пересылает ответ во внешний источник
//Использование событий позволяет выполнить запрос без каких либо пауз (какие появлялись бы при использовании функции 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