我的代码运行4个函数来填充信息(使用Invoke)到类,如:
class Person
{
int Age;
string name;
long ID;
bool isVegeterian
public static Person GetPerson(int LocalID)
{
Person person;
Parallel.Invoke(() => {GetAgeFromWebServiceX(person)},
() => {GetNameFromWebServiceY(person)},
() => {GetIDFromWebServiceZ(person)},
() =>
{
// connect to my database and get information if vegeterian (using LocalID)
....
if (!person.isVegetrian)
return null
....
});
}
}
我的问题是:如果他不是素食主义者,我不能返回null,但我希望能够停止所有线程,停止处理并返回null。如何实现?
答案 0 :(得分:8)
要尽早退出Parallel.Invoke
,您必须做三件事:
AggregateException
,如Jon的回答所示。IsCancellationRequested
财产时,这才有意义。您的代码将如下所示:
var cts = new CancellationTokenSource();
try
{
Parallel.Invoke(
new ParallelOptions { CancellationToken = cts.Token },
() =>
{
if (!person.IsVegetarian)
{
cts.Cancel();
throw new PersonIsNotVegetarianException();
}
},
() => { GetAgeFromWebServiceX(person, cts.Token) },
() => { GetNameFromWebServiceY(person, cts.Token) },
() => { GetIDFromWebServiceZ(person, cts.Token) }
);
}
catch (AggregateException e)
{
var cause = e.InnerExceptions[0];
// Check if cause is a PersonIsNotVegetarianException.
}
然而,正如我所说,取消令牌只有你能检查它们才有意义。所以GetAgeFromWebServiceX
内部应该有机会检查取消令牌并提前退出,否则,将令牌传递给这些方法是没有意义的。
答案 1 :(得分:4)
好吧,你可以从你的行动中抛出异常,在AggregateException
中捕捉GetPerson
(即在Parallel.Invoke
附近放置一个try / catch块),检查它是否正确异常,并返回null。
除了停止所有线程之外,它实现的所有内容。我认为你不可能轻易地阻止已经在运行的任务,除非你开始进入取消令牌。您可以通过保留boolean
值来指示进一步执行任务,以指示到目前为止任何任务是否已失败,并在开始之前让每个任务检查...它有点难看,但它会奏效。
我怀疑使用“完整”任务代替Parallel.Invoke
会使所有这些更加优雅。
答案 2 :(得分:1)
当然,您还需要首先从数据库加载Person
吗?因为您的代码使用null调用Web服务。
如果你的逻辑真的是顺序的,那就按顺序进行,只做并行的事情。