Multithreading 调用TTask.WaitForAny后获取失败任务的索引

Multithreading 调用TTask.WaitForAny后获取失败任务的索引,multithreading,delphi,Multithreading,Delphi,考虑以下示例: 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

考虑以下示例:

 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;
当其中一个任务失败时,WaitForAny抛出异常,并且res变量未分配已完成任务的索引。相反,它包含“-1”(先前分配的)

在C#(TPL)
Task.WaitAny
中也会抛出异常,但它会返回失败任务的索引

有没有办法分配RES变量或获取失败任务的索引?

您写道:

在C#(TPL)
Task.WaitAny
中也会抛出异常,但它会返回失败任务的索引

那不是真的。考虑下面的C语言程序:

使用系统;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
Task t1=Task.Run(()=>{抛出新异常(“任务1”);});
Task t2=Task.Run(()=>{抛出新异常(“任务2”);});
int index=Task.WaitAny(新任务[]{t1,t2});
控制台写入线(索引);
Console.ReadLine();
}
}
}
这两个任务都会抛出异常,但
WaitAny
不会抛出异常。它返回最先完成的任务的索引值,即使该任务引发了异常

相反,如果要完成的第一个任务通过引发异常来引发异常,那么Delphi
TTask.WaitForAny
方法将引发异常。在这种情况下,由于函数引发异常时未分配函数返回值,因此需要找到不同的方法来识别导致
WaitForAny
返回的任务。例如,这里有一个相当蹩脚的方法:

{$APPTYPE控制台}
使用
System.SysUtils,System.Threading;
类型
ETaskException=类(异常)
私有的
FTaskIndex:整数;
公众的
构造函数创建(常量消息:字符串;常量任务索引:整数);
属性TaskIndex:整数读取FTaskIndex;
结束;
构造函数ETaskException.Create(const-Msg:string;const-TaskIndex:Integer);
开始
继承创建(Msg);
FTaskIndex:=任务索引;
结束;
变量
t1,t2:ITask;
i、 res:整数;
开始
t1:=TTask.Run(
程序
开始
睡眠(150);
引发ETaskException.Create('任务失败',0);
结束
);
t2:=TTask.Run(
程序
开始
睡眠(100);
引发ETaskException.Create('Task failed',1);
结束
);
尝试
res:=TTask.WaitForAny([t1,t2]);
Writeln('任务成功,索引'+IntToStr(res));
除了
在E:EAggregateException上开始
对于i:=0到E.Count-1,开始
WriteLn('任务失败,索引'+
IntToStr((E.InnerExceptions[i]作为etaskeException.TaskIndex));
结束;
结束;
结束;
ReadLn;
结束。
虽然我在这里循环了聚合异常,但我相信只有一个内部异常与
WaitForAny


您最好只是在任务上循环寻找一个
状态
等于
TTaskStatus.Exception的任务。我希望您必须跟踪that@DavidHeffernan这是一种语言行为?i、 当函数抛出异常时,结果赋值永远不会发生?如果函数引发,则函数返回值未定义。所有语言都相同,包括C#。所以不,我不认为WaitAny会返回任何东西,如果它引发了任何问题。@DavidHeffernan好吧,是的,C#中的WaitAny不会抛出异常并返回第一个完成任务的索引。因此,我的解决方案是迭代这些任务,并获得第一个已完成的任务。你是说等待吗?我想在这里写一个答案,但我想知道我们是否在谈论同一件事。