我有一个方法可以创建一个任务,并将Action作为一个新任务执行,一段时间后如果它没有完成,它会杀死它。这是代码:
static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
if (!task.Wait(timeSpan))
{
Console.WriteLine("Time exceeded. Aborted!");
}
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
这个方法我从另一个地方调用。
public static async Task<List<LMAXData>> GetExposure()
{
var accountsPositions = new List<LMAXData>();
foreach (var account in accounts)
{
LMAXInterfаce lmax = new LMAXInterfаce(account.user, account.password);
ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(5000), lmax.StartInterface);
accountsPositions.AddRange(lmax.GetLMAXData().GroupBy(x => x.instrument).Select(i => i.First()).ToList());
}
return accountsPositions;
}
我的最终目标是为每个帐户创建一个并行任务,它将启动lmax. StartInterface
方法,该方法将收集数据并将其添加到我的帐户位置
本地列表中。
但问题是,如果你有10个账户,它太慢了,因为每个账户收集数据需要5秒钟。
我想并行运行这10个帐户任务,等待5秒,然后全部杀死并获取结果。有办法做到吗?
首先,你在执行时间限制中做了一些奇怪的事情,因为你从来没有“中止”或“杀死”任务。任务最终会完成,但你“忘记”了它。你也没有返回任务结果。
关于你的问题,是的,这是可能的,也很容易,只要启动任务并执行WaitAny(任务,timeSpan)https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.waitany?view=net-6.0,然后检查除了从WaitAny返回的任务之外还完成了什么,并获取Result。
然而,我会重新考虑设计,因为结构似乎很奇怪。GetExposure已经是一个异步任务,您可以简单地使用它。
// this will create 10 tasks
var tasks = Enumerable.Range(1,10).Select(_=>GetExposure()).ToArray();
//this will wait for any finished or proceed
var tn = Task.WaitAny(tasks, timeSpan);
if(tn!=-1){
DoSomthing(tasks[tn].Result);
}
// check other if needed
foreach(t in tasks){
if(t.IsCompleted){
DoSomthing(t.Result);
}
}
要正确取消任务,您应该实现KunelationToken