C# 多线程 06-使用并发集合 03-改变 ConcurrentStack 异步处理顺序
🏷️ 《C# 多线程》
改变 ConcurrentStack 异步处理顺序
该示例同 02-使用 ConcurrentQueue 实现异步处理 大部分是一样的,只是将 ConcurrentQueue
改成了 ConcurrentStack
。
Queue 是 FIFO(先进先出),Stack 则是 LIFO(后进先出),执行的顺序不一样。
csharp
/// <summary>
/// 改变 ConcurrentStack 异步处理顺序
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Task t = RunProgram();
t.Wait();
Console.ReadLine();
}
static async Task RunProgram()
{
var taskStack = new ConcurrentStack<CustomTask>();
var cts = new CancellationTokenSource();
// 异步创建任务
var taskSource = Task.Run(() => TaskProducer(taskStack));
// 创建 4 个任务处理线程
Task[] processors = new Task[4];
for (int i = 1; i <= 4; i++)
{
string processorId = i.ToString();
processors[i - 1] = Task.Run(() => TaskProcessor(taskStack, $"Processor {processorId}", cts.Token));
}
// 等待创建任务结束
await taskSource;
// 延迟 2 秒发送取消指令,确保创建的任务被处理完
cts.CancelAfter(TimeSpan.FromSeconds(2));
// 等待所有消费结束
await Task.WhenAll(processors);
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="queue"></param>
/// <returns></returns>
static async Task TaskProducer(ConcurrentStack<CustomTask> queue)
{
for (int i = 1; i <= 20; i++)
{
await Task.Delay(50);
// 创建任务加入队列
var workItem = new CustomTask { Id = i };
queue.Push(workItem);
Console.WriteLine($"Task {workItem.Id} has been posted");
}
}
/// <summary>
/// 任务处理程序
/// </summary>
/// <param name="queue">队列</param>
/// <param name="name">消费程序名</param>
/// <param name="token">令牌(取消任务用)</param>
/// <returns></returns>
static async Task TaskProcessor(ConcurrentStack<CustomTask> queue, string name, CancellationToken token)
{
CustomTask workItem;
bool dequeueSuccesful = false;
// 若任务未取消,则延迟随机时间后尝试从队列中获取任务
await GetRandomDelay();
do
{
dequeueSuccesful = queue.TryPop(out workItem);
if (dequeueSuccesful)
{
Console.WriteLine($"Task {workItem.Id} has been processed by {name}");
}
await GetRandomDelay();
} while (!token.IsCancellationRequested);
}
/// <summary>
/// 获取随机的延迟时间
/// </summary>
/// <returns></returns>
static Task GetRandomDelay()
{
int delay = new Random(DateTime.Now.Millisecond).Next(1, 500);
return Task.Delay(delay);
}
private class CustomTask
{
public int Id { get; set; }
}
运行结果
txt
Task 1 has been posted
Task 2 has been posted
Task 3 has been posted
Task 4 has been posted
Task 4 has been processed by Processor 3
Task 1 has been processed by Processor 1
Task 3 has been processed by Processor 4
Task 2 has been processed by Processor 2
Task 5 has been posted
Task 5 has been processed by Processor 4
Task 6 has been posted
Task 7 has been posted
Task 8 has been posted
Task 9 has been posted
Task 10 has been posted
Task 8 has been processed by Processor 4
Task 7 has been processed by Processor 2
Task 10 has been processed by Processor 1
Task 9 has been processed by Processor 3
Task 11 has been posted
Task 12 has been posted
Task 13 has been posted
Task 14 has been posted
Task 14 has been processed by Processor 1
Task 13 has been processed by Processor 3
Task 12 has been processed by Processor 1
Task 15 has been posted
Task 16 has been posted
Task 17 has been posted
Task 17 has been processed by Processor 2
Task 16 has been processed by Processor 4
Task 15 has been processed by Processor 4
Task 18 has been posted
Task 19 has been posted
Task 19 has been processed by Processor 3
Task 20 has been posted
Task 20 has been processed by Processor 4
Task 18 has been processed by Processor 1
Task 11 has been processed by Processor 1
Task 6 has been processed by Processor 1