使用var参数的匿名线程过程

问题描述 投票:0回答:1

这不是我第一次遇到与此类似的问题:如何从匿名线程(或TTask)中获取返回参数值的var参数?

我需要运行一个耗时且消耗大量CPU的过程,在运行过程中,它将在过程中填充一条记录的LOG信息,稍后将在其他模块中使用该信息。一旦有其他进程要同时运行,我将这个过程放在AnoynymousThread中。不幸的是,完成后,我无法使用LOG的记录数据,因为它为空。

我应该怎么做才能在线程内部处理期间填充此记录?

查看我的代码:[UNIT]

unit UntStringThread;

interface    
uses
   System.Classes,
   System.SysUtils,
   System.Threading;

   TYPE
    TRCLog = record
       logprocess : Tstringlist;
       logrecord  : Array of Tstringlist;
    end;    

    Procedure DoBigProcess (var pRecLog : TRClog; piterations : integer);
    Procedure MajorProcessing (var pmainLog : TRCLog);

implementation 

   Procedure DoBigProcess (var pRecLog : TRClog; piterations : integer);
   Var
       localLog                 : TRCLog;
       lrows,lrecs, ltotalrecs  : integer;
       strlogrecords            : string;

   begin
        //Define pRecLog.logrecord array size
        setlength(precLog.logrecord, piterations);

        // Starts the piterations of the main process which will generates a LOG
        for lrows := 1 to piterations do
        begin
              // ... here goes critial processing that generates

              // Generate Log for the current iteration
              pRecLog.logprocess.Add('Iteration : ' + lrows.Tostring + ' ... log data about current iteration ...');

              // ... other processing goes here. Suppose total records is 10
              ltotalrecs := 10;


              // Generate Log for each record
              pRecLog.logrecord[lrows-1] := Tstringlist.Create;
              for lrecs := 1 to ltotalrecs do
              begin
                     //  some additionl processing here that generates detail log of records being processed
                     strlogrecords := '    Record : ' + lrecs.tostring + '... log data about current record being processed';
                     pRecLog.logrecord[lrows-1].Add(strlogrecords);
              end;
              pRecLog.logrecord[lrows-1].Add(' ');
         end;
   end;


   Procedure MajorProcessing (var pmainLog : TRCLog);
   var
       llog       : TRClog;
       litems     : integer;

   begin
        // some initialization processing here
        // ...
        litems := 10;

        // Runs BigProcess in an Anonymous  Thread
        llog := pmainlog;
        TThread.CreateAnonymousThread(procedure
                                      begin
                                            DoBigProcess (lLog, litems);
                                      end);

        // Continuing process other stuff here

   end;
end.

主程序

program ProjThreadParameter;
{$APPTYPE CONSOLE}
{$R *.res}
uses
  System.SysUtils,
  System.Classes,
  UntStringThread in 'UntStringThread.pas';
var
     idxlog, idxrecord: integer;
     logmain : TRClog;
begin
  try
      logmain.logprocess := Tstringlist.Create;
      MajorProcessing (logmain);

      {==> This call, without Thread, works fine}
      //DoBigProcess(logmain,10);

      for idxlog :=0  to logmain.logprocess.Count-1 do
      begin
           Writeln(logmain.logprocess[idxlog]);
           for idxrecord :=0 to logmain.logrecord[idxlog].count-1 do
               Writeln(logmain.logrecord[idxlog][idxrecord])
      end;
      Readln;

      // PROBLEM ==> when using Thread logmain record returned empty !!

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

我研究了几年前的一个先前的问题,但是这次我无法使其起作用。iTask - values parameters to anonymous procedure

感谢您的帮助!

multithreading delphi parameter-passing
1个回答
0
投票

IFuture是ITask并发过程的并发函数。

如果创建依赖于循环索引的函数变量,则可以将变量的值绑定到函数中以用作Future。

此版本创建一个字符串数组。同样适用于字符串列表返回类型。

program ProjThreadLogging;
{$APPTYPE CONSOLE}
uses
     System.SysUtils,
     System.Classes,
     System.Threading;

const
     procs = 8;

var
     idxlog     : integer;
     s          : string;
     futurefunc : TFunc<string>;
     logstrs    : array [1..procs] of IFuture<string>;

function CreateIdxLogFunc(idxlog:integer):TFunc<string>;
     begin
       Result := function:string
                 begin
                    {Some calculation that takes time}
                    Sleep(1000*idxlog);
                    Result:='Proc ' + idxlog.ToString;
                 end;
     end;

begin
     for idxlog in [1..procs] do begin
         futurefunc      :=   CreateIdxLogFunc(idxlog);
         logstrs[idxlog] :=   TTask.Future<string>( futurefunc );
     end;

     for idxlog in [1..procs] do begin
         writeln(logstrs[idxlog].Value);
     end;

     Readln;
end.  
© www.soinside.com 2019 - 2024. All rights reserved.