我想并行加载包含任务的列表,然后并行执行这些任务。 任务将方法作为操作,但我需要该方法来处理每个任务的不同对象。但我无法传递参数。
所以我正在考虑这样的解决方案:
public static Order order = new Order();
public static Queue<SubOrder> subsQ = order.SubOrders;
public void Work()
{
Task[] taskList = TaskMaker(order.SubOrders.Count);
Task.WaitAll(taskList);
}
public Task[] TaskMaker(int orderCount)
{
Task[] taskList = new Task[order.SubOrders.Count];
Parallel.For(0, taskList.Length, i => taskList[i] = new Task(ExecuteSubOrder) );
return taskList;
}
public void ExecuteSubOrder()
{
SubOrder subO = subsQ.Dequeue();
// ... execute suborder, some webrequest etc.
ordersCompletedTable.Execute(TableOperation.Insert(new SubOrder(subO.SubOrderId, subO.Status)),
new TableRequestOptions() { RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3) });
}
public class Order
{
public Queue<SubOrder> SubOrders { get; set; }
}
该方法执行订单,并在每个完成的订单上记录在azure表中。 该方法为使用Parallel.For放入Task []的每个任务的新顺序排队,这样我就可以使用该任务数组调用Parallel.WaitAll。
可以这样做,还是应该以不同的方式做? 我在这里并行完成工作吗?
答案 0 :(得分:2)
您正在使用Parallel.For
为每个子订单创建新任务,但随后从任务中的共享数据结构中检索子订单。这不是理想的路线,因为当每个任务开始执行时,它会导致竞争危险(如果不同步)或瓶颈(如果同步)。
相反,更改ExecuteSubOrder
方法的定义以接受其子顺序作为参数,然后使用Parallel.ForEach
将子顺序并行化到任务上。 Parallel.ForEach
还会在返回之前等待所有子订单完成。
public void Work()
{
Parallel.ForEach(order.SubOrders, ExecuteSubOrder);
}
public void ExecuteSubOrder(SubOrder subO)
{
// ... execute suborder, some webrequest etc.
ordersCompletedTable.Execute(TableOperation.Insert(new SubOrder(subO.SubOrderId, subO.Status)),
new TableRequestOptions() { RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3) });
}