我试图想出最好的方法来运行异步方法的迭代。
基本上,我在第一时间内运行了第一个TimeSpan
和一个Dictionary<Item,TimeSpan>
。
例如:
var iteration = new TimeSpan().FromSeconds(60);
var items = new Dictionary<Item,TimeSpan>();
items.Add(item1,new TimeSpan().FromSeconds(10))
items.Add(item2,new TimeSpan().FromSeconds(30))
可以安全地假设:
TimeSpan
项始终为<
而不是iteration
iteration
,当转换为秒时,始终适合字典中N
个TimeSpan
个项目(如果迭代时间为60秒,则项目的时间跨度为1或2或3或6或10或15等等。对于每个Item
我需要每X
ms运行一个异步方法(由字典中的TimeSpan
定义。例如:
public async Task<int> MyMethod(Item item)
{
return await 3; // In reality something is done and a result is returned
}
这意味着对于示例中的两个项目和60秒的时间跨度,如果我从T00:00
开始,我需要为MyMethod
运行item1
6次(at {{ 1}},T00:00
,T00:10
等)和T00:20
2次(item2
和T00:00
)。
现在,这个部分相对简单,我稍微挣扎的是让T00:30
在60秒内再次重复,并确保它开始是否完成了前一个。例如,如果iteration
的{{1}}需要12秒才能完成,我仍然希望在MyMethod
秒后开始另一次迭代(这意味着在某个特定时间点我会有多个执行item1
60
有效。
我尝试做的事情是MyMethod
对item1
void
进行MyMethod
调用,但无法使其发挥作用。
答案 0 :(得分:1)
我自己实际上已经解决了这个问题。
Iteration
是一个代表迭代的类:
public void RunIterations()
{
var iterations = new List<Iteration>();
// Adding items that represent the iterations to run
// Here we're creating an array of tasks for each iteration
// The running RunIteration for each iteration that needs to be created
// However, the tasks will never finish unless the cancellation is requested (as we can see in RunIteration method).
var iterationTasks = new Task[iterations.Count];
var iterationIndex = 0;
foreach (Iteration iteration in iterations)
{
iterationTasks[iterationIndex] = RunIteration(iteration);
iterationIndex++;
}
Task.WaitAll(iterationTasks);
}
private async Task RunIteration(Iteration iteration)
{
// We're creating an endless loop that will keep starting the RunAsync() for the iteration until the cancellation is requested.
while (!_cancellationTokenSource.IsCancellationRequested)
{
// We're running the RunAsync() without waiting for it to finish.
// It's done on purpose: in case any stages in the iteration take more time than expected
// then another iteration is started in parallel as the previous one is finishing.
iteration.RunAsync().ContinueWith(
task => {
DoSomethingWithResult(task.Result);
});
// Waiting for the duration of the iteration to start the next one.
await Task.Delay(( new TimeSpan().FromSeconds(60));
}
}