multithreading - Getting the index of a failed Task after calling TTask.WaitForAny -


consider following example:

 t1 := ttask.run(     procedure     begin       sleep(random(1000) + 100);       raise exception.create('error message 1');     end   );    t2 := ttask.run(     procedure     begin       sleep(random(1000) + 100);       raise exception.create('error message 2');     end   );    res := -1;   try     res:= ttask.waitforany([t1, t2]);   except   end;    write('index: ' + inttostr(res)); // prints "-1"   readln; 

when 1 of tasks fails waitforany throws exception , res variable not assigned index of completed task. instead contains "-1" (assigned earlier).

in c# (tpl) task.waitany throws exception, returns index of failed task.

is there way res variable assigned or index of failed task?

you wrote:

in c# (tpl) task.waitany throws exception, returns index of failed task.

that's not true. consider following c# program:

using system; using system.threading.tasks;  namespace consoleapplication1 {     class program     {         static void main(string[] args)         {             task t1 = task.run(() => { throw new exception("task 1"); });             task t2 = task.run(() => { throw new exception("task 2"); });             int index = task.waitany(new task[] { t1, t2 });             console.writeline(index);             console.readline();         }     } } 

both tasks throw exceptions, waitany not. returns index value of whichever task completed first, if task threw exception.

by contrast, delphi ttask.waitforany method raise exception if first task complete raising exception. in case, since function return values not assigned when function raises exception, need find different way identify task caused waitforany return. instance, here rather lame way it:

{$apptype console}  uses   system.sysutils, system.threading;  type   etaskexception = class(exception)   private     ftaskindex: integer;   public     constructor create(const msg: string; const taskindex: integer);     property taskindex: integer read ftaskindex;   end;  constructor etaskexception.create(const msg: string; const taskindex: integer); begin   inherited create(msg);   ftaskindex := taskindex; end;  var   t1, t2: itask;   i, res: integer;  begin  t1 := ttask.run(     procedure     begin       sleep(150);       raise etaskexception.create('task failed', 0);     end   );    t2 := ttask.run(     procedure     begin       sleep(100);       raise etaskexception.create('task failed', 1);     end   );    try     res := ttask.waitforany([t1, t2]);     writeln('task succeeded, index ' + inttostr(res));   except     on e:eaggregateexception begin       := 0 e.count-1 begin         writeln('task failed, index ' +            inttostr((e.innerexceptions[i] etaskexception).taskindex));       end;     end;   end;    readln; end. 

although i've looped on aggregate exceptions here, believe there ever 1 inner exception waitforany.

you may better off looping on tasks looking 1 has status equal ttaskstatus.exception.


Comments