Многопоточность

отредактировано 14:23 Раздел: FastScript
FastScript не работает в многопоточном режиме! Точнее работает но глючит по черному ;)
По порядку: запускаю несколько потоков, в каждом потоке свой DataModule, на нем TfsScript, TfsPascal, TfsClassesRTTI и т. д. Выполняется один и тот же скрипт, он читает таблицу и пишет в файл(для каждого потока свой) несколько полей примерно так:
field1
field2
field3
field1
field2
field3
...

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

Комментарии

  • отредактировано 14:23
    если потоки запускаются одновременно, а точнее последовательно, а запись ведется в один файл, то просто срабатываем режим опережения, записал то к кто в это время отработал
  • отредактировано 14:23
    Извините, пропустил ваш коментарий по поводу разных файлов, есть кое какие соображения, но их надо сформулировать должным образом. Постараюсь подумать над этим.
  • отредактировано 14:23
    Отвечаю на свой же вопрос ;)
    Проблема с многопоточностью в использовании глобального модуля! См. fsGlobalUnit.
    Вывод: для каждого потока нужно использовать свой "глобальный" модуль.
    1.Переписываем нужные юниты fs_iXXXrtti.pas так:
    ...........
    type
      TfsClassesRTTI = class(TComponent); // fake component
    
    
    type
      TFunctions = class(TObject)
      private
        function CallMethod(Instance: TObject; ClassType: TClass;
          const MethodName: String; var Params: Variant): Variant;
        function GetProp(Instance: TObject; ClassType: TClass;
          const PropName: String): Variant;
        procedure SetProp(Instance: TObject; ClassType: TClass;
          const PropName: String; Value: Variant);
      public
        FParentUnit:TfsScript;
        constructor Create(ParentUnit:TfsScript);
        destructor Destroy; override;
      end;
    
    implementation
    
    
    var
      Functions: TFunctions;
    
    
    { TFunctions }
    
    constructor TFunctions.Create;
    begin
      FParentUnit :=ParentUnit;
      with FParentUnit do
      begin
        AddedBy := Self;
        AddConst('fmCreate', 'Integer', fmCreate);
    
    
    ...........
    
    destructor TFunctions.Destroy;
    begin
      try
        if FParentUnit <> nil then
          FParentUnit.RemoveItems(Self);
      except
      end;  
      inherited;
    end;
    
    
    ..........
    
    initialization
      Functions := TFunctions.Create(fsGlobalUnit);
    
    finalization
      Functions.Free;
    
    end.
    
    Определение TFunctions выносим в секцию interface.
    Добавляем поле FParentUnit:TfsScript;
    Меняем констрактор constructor Create(ParentUnit:TfsScript);
    и дестрактор для работы с FParentUnit.
    В секции initialization теперь будем вызывать:
    Functions := TFunctions.Create(fsGlobalUnit);
    То есть для однопоточного режима практически ничего не меняется!

    2. В многопоточном режиме, в каждом потоке:
    //создаем еще один TfsScript, он будет глобальным для потока
       fsScriptParent:=TfsScript.Create(nil);
    // определяем базовые типы
    // вырезано из функции fsGlobalUnit
        with fsScriptParent do
        begin
          AddType('Byte', fvtInt);
          AddType('Word', fvtInt);
          AddType('Integer', fvtInt);
          AddType('Longint', fvtInt);
          AddType('Cardinal', fvtInt);
          AddType('TColor', fvtInt);
          AddType('Boolean', fvtBool);
          AddType('Real', fvtFloat);
          AddType('Single', fvtFloat);
          AddType('Double', fvtFloat);
          AddType('Extended', fvtFloat);
          AddType('Currency', fvtFloat);
          AddType('TDate', fvtFloat);
          AddType('TTime', fvtFloat);
          AddType('TDateTime', fvtFloat);
          AddType('Char', fvtChar);
          AddType('String', fvtString);
          AddType('Variant', fvtVariant);
          AddType('Pointer', fvtVariant);
          AddType('Array', fvtArray);
          AddType('Constructor', fvtConstructor);
    
          AddConst('True', 'Boolean', True);
          AddConst('False', 'Boolean', False);
          AddConst('nil', 'Variant', 0);
          AddConst('Null', 'Variant', Null);
        end;
    // Вызываем функции регистрации обьектов из всех нужных модулей
      fs_iclassesrtti.TFunctions.Create(fsScriptParent);
      fs_idbrtti.TFunctions.Create(fsScriptParent);
      fs_ibdertti.TFunctions.Create(fsScriptParent);
    // ... и так далее для всех нужных модулей
    // Присваеваем рабочему fsScript ссылку на "глобальный" модуль
      fsScript1.Parent := fsScriptParent;
    
    

    Все, теперь с fsScript1 можно работать! ;)


Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.