Reputation: 175
I want to in parallel load a list with tasks, and then in parallel execute those tasks. The tasks take a method as action, but I need that method to work on different objects for every task. But I couldn't pass in parameters.
So I'm thinking of a solution like this:
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; }
}
The method executes an order, and upon every completed order, records that in an azure table. The method dequeues a new order for every task that I put into a Task[] with Parallel.For, so that I can then call Parallel.WaitAll with that task-array.
Can this be done so, or should I do it differently? Am I getting the job done in parallel here?
Upvotes: 2
Views: 286
Reputation: 54887
You're using Parallel.For
to create a new task for each suborder, but then retrieving the suborders from a shared data structure within the tasks. This is not the ideal route, since it will lead to a race hazard (if unsynchronized) or a bottleneck (if synchronized) when each task starts executing.
Instead, alter the definition of the ExecuteSubOrder
method to accept its suborder as parameter, then use Parallel.ForEach
to parallelize the suborders onto tasks. Parallel.ForEach
also takes care of waiting for all suborders to complete before returning.
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) });
}
Upvotes: 2