Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > DLL на Delphi Embarcadero, IIS, многопоточность, р


Автор: forSale 20.4.2014, 08:41
Есть код:
   
Код

 { Invokable implementation File for TBillingGaz which implements IBillingGaz }
    
    unit BillingGazImpl;
    
    interface
    
    uses InvokeRegistry, Types, XSBuiltIns, BillingGazIntf, WebService.ReturnRecord,
         Classes, SyncObjs, SysUtils, StrUtils, Messages;
    
    type
    
      { TBillingGaz }
      TBillingGaz = class(TInvokableClass, IBillingGaz)
      public
        function echoDouble(const Value: Double): Double; stdcall;
        function GetBill(const AccountNo: string; const ConsumValue: Integer): TBillForClient; stdcall;
      end;
    
    
    type
      TNThread = class(TThread)
      private
        FAcc : string;
        FCons : Integer;
        procedure Sync;
      protected
        procedure Execute; override;
      public
        property AccTh : string read FAcc write FAcc;// write Fcons;
        property Cons : Integer read Fcons write Fcons;
      end;
    
    var
      acc: string;
      cons1, i: Integer;
      CS: TCriticalSection;
      mBillingGaz : TBillingGaz;
    
    implementation
    
    uses WebService.CalcPayAmount{, BillingGazThread};
      
    
    function TBillingGaz.echoDouble(const Value: Double): Double; stdcall;
    begin
      { TODO : Implement method echoDouble }
      Result := Value;
    end;
    
    function TBillingGaz.GetBill(const AccountNo: string; const ConsumValue: Integer): TBillForClient; stdcall;
    var
      NewThread: TNThread;
      prevAcc : string;
    begin
      Result := TBillForClient.Create;
   
      cons1 := 0;
      acc :=  AccountNo;
      prevAcc := AccountNo;
      Result.FullName := acc + ' ' + FormatDateTime('hh:mm:ss.zzz', Now);
   
      NewThread:= TNThread.Create(true);
      NewThread.FreeOnTerminate:=true;
      NewThread.Priority:=tpLower;
      NewThread.AccTh := prevAcc;
      NewThread.Resume;
      Sleep(5);
   
      if Copy(Result.FullName, 1, 9) <> acc then
        Result.FullName := Result.FullName + ' ' + acc + ' ' + prevAcc;
      Result.ErrorCode := NewThread.Cons;
    end;
    
    
    procedure TNThread.Execute;
    begin
      CS.Enter;
      case AnsiIndexText(Copy(AccTh, 1, 2), ['00','01','02','03','04','05']) of
        0 : begin
          Cons := 1;
        end;
        1 : begin
          Cons := 2;
        end;
        2 : begin
          Cons := 3;
        end;
        3 : begin
          Cons := 4;
        end;
        4 : begin
          Cons := 5;
        end;
        5 : begin
          Cons := 6;
        end
      else
        Cons := ERROR_WRONG_ACCOUNT_NO;
      CS.Leave;
    end;
    
    procedure TNThread.Sync;
    begin
    //  mBillingGaz.Billingcons := cons1;
    end;
    
    
    initialization
    { Invokable classes must be registered }
       InvRegistry.RegisterInvokableClass(TBillingGaz);
       CS := TCriticalSection.Create;
    
    end.


Есть биллинговый проект. Он рабочий. Появилась необходимость создать веб-сервис для предоставления суммы к оплате за газ в ответ на запрос с передачей лицевого счета и текущего показания счетчика. Чтобы не изобретать велосипед, было решено взять готовый модуль проекта, отвечающий за расчеты и создать на его основе DLL для веб-сервера. Проведено тестирование сервиса: поочередно серверу передаются заранее заготовленные лицевые счета и показания, ответ выводится в МЕМО на клиенте. Это работает нормально, когда только один клиент обращается. Программа клиента была скопирована и запущена параллельно. Таким образом два клиента одновременно работают. У них 2 разных списка с лицевыми и показаниями. Обе программы работают какое-то время, потом появляется ошибка: List index out of bounds().
Порывшись в интернете обнаружил, что IIS работает в несколько потоков. А это чревато при работе с TList, который не потокобезопасен. При попытке перейти на TThreadList наткнулся на такую проблему: список на основе TList объявляется как:
var
  переменная: TList<какой-то класс>;

такая конструкция по-видимому TThreadList не поддерживается. Долго не заморочиваясь, решил создавать потоки прямо внутри удаленно вызываемой функции GetBill. Но тут наткнулся на проблему синхронизации. Бывает так, что запросы к серверу поступают одновременно и результат второго по очереди запроса попадает к первому.

Не удается организовать работу потоков. Что-то я делаю не так, возможно вообще в корне неверное, но не пойму как по-другому работать с потоками.

Автор: Romikgy 20.4.2014, 21:33
ну так почитайте как правильно работать с многопоточностью в дельфи

Автор: forSale 21.4.2014, 15:05
Цитата(Romikgy @  20.4.2014,  21:33 Найти цитируемый пост)
ну так почитайте как правильно работать с многопоточностью в дельфи 

Читаю. Честно. =)
Но там такой материал, что легче спросить как дальше быть.

Автор: Romikgy 22.4.2014, 10:32
нет , не легче...
легче один раз самому разобраться , чем потом каждый раз спрашивать 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)