提问者:小点点

用定时器并行执行多个任务


我有一个方法可以创建一个任务,并将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秒,然后全部杀死并获取结果。有办法做到吗?


共1个答案

匿名用户

首先,你在执行时间限制中做了一些奇怪的事情,因为你从来没有“中止”或“杀死”任务。任务最终会完成,但你“忘记”了它。你也没有返回任务结果。

关于你的问题,是的,这是可能的,也很容易,只要启动任务并执行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