My blog post cho biết cách thực hiện điều này cả với Tác vụ và Tác vụ và cung cấp dự án mẫu bạn có thể tải xuống và chạy để xem cả hai đang hoạt động.
Với hành động
Nếu sử dụng Tác vụ, bạn có thể sử dụng chức năng .Net Parallel.Invoke được tích hợp sẵn. Ở đây chúng tôi giới hạn nó để chạy tối đa 3 luồng song song.
var listOfActions = new List<Action>();
for (int i = 0; i < 10; i++)
{
// Note that we create the Action here, but do not start it.
listOfActions.Add(() => DoSomething());
}
var options = new ParallelOptions {MaxDegreeOfParallelism = 3};
Parallel.Invoke(options, listOfActions.ToArray());
Với Nhiệm vụ
Vì bạn đang sử dụng Công việc ở đây, mặc dù không có tích hợp chức năng. Tuy nhiên, bạn có thể sử dụng cái mà tôi cung cấp trên blog của mình.
/// <summary>
/// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel.
/// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
/// </summary>
/// <param name="tasksToRun">The tasks to run.</param>
/// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, CancellationToken cancellationToken = new CancellationToken())
{
StartAndWaitAllThrottled(tasksToRun, maxTasksToRunInParallel, -1, cancellationToken);
}
/// <summary>
/// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel.
/// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
/// </summary>
/// <param name="tasksToRun">The tasks to run.</param>
/// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param>
/// <param name="timeoutInMilliseconds">The maximum milliseconds we should allow the max tasks to run in parallel before allowing another task to start. Specify -1 to wait indefinitely.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, int timeoutInMilliseconds, CancellationToken cancellationToken = new CancellationToken())
{
// Convert to a list of tasks so that we don't enumerate over it multiple times needlessly.
var tasks = tasksToRun.ToList();
using (var throttler = new SemaphoreSlim(maxTasksToRunInParallel))
{
var postTaskTasks = new List<Task>();
// Have each task notify the throttler when it completes so that it decrements the number of tasks currently running.
tasks.ForEach(t => postTaskTasks.Add(t.ContinueWith(tsk => throttler.Release())));
// Start running each task.
foreach (var task in tasks)
{
// Increment the number of tasks currently running and wait if too many are running.
throttler.Wait(timeoutInMilliseconds, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
task.Start();
}
// Wait for all of the provided tasks to complete.
// We wait on the list of "post" tasks instead of the original tasks, otherwise there is a potential race condition where the throttler's using block is exited before some Tasks have had their "post" action completed, which references the throttler, resulting in an exception due to accessing a disposed object.
Task.WaitAll(postTaskTasks.ToArray(), cancellationToken);
}
}
Và sau đó tạo ra danh sách các nhiệm vụ và gọi hàm có họ chạy, với nói tối đa là 3 đồng thời cùng một lúc, bạn có thể làm điều này:
var listOfTasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
var count = i;
// Note that we create the Task here, but do not start it.
listOfTasks.Add(new Task(() => Something()));
}
Tasks.StartAndWaitAllThrottled(listOfTasks, 3);
Có thể trùng lặp http://stackoverflow.com/questions/2898609/system-threading-tasks-limit-the-number-of-concurrent-tasks – Samich