C# 实现异步队列中等待await执行完毕再执行下一个任务
普通的异步队列可以回看我之前一篇博客:https://www.cnblogs.com/log9527blog/p/16517315.html
但是之前实现的异步队列中,任务如果出现await等待,会认为该任务已经完成,并且开始下一个任务。所有为了实现异步队列中等待await执行完毕再执行下一个任务,下面重写了新的异步队列:
using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; namespace Text { /// <summary> /// 异步任务队列 /// <para>同步执行,等待委托内的await完成再执行下一个委托,并且自动取消中间的任务</para> /// </summary> public class SynchronizeTaskQueue { #region 执行 /// <summary> /// 执行多个同步操作(同步执行,取消中间未执行的任务,传进来的委托需要try...catch...) /// </summary> /// <param name="func">异步操作</param> public void ExecuteFromResult(Func<Task> func) { AddPendingAwaitTaskToQueue(func); Task.Run(async () => { await ExcuteTaskQueue(); }); } #endregion #region 添加任务 /// <summary> /// 添加待执行任务到队列 /// </summary> /// <param name="func"></param> /// <returns></returns> private void AddPendingAwaitTaskToQueue(Func<Task> func) { // 添加队列,加锁。 lock (_funcQueue) { // 添加任务 _funcQueue.Enqueue(func); var newTask = new Task<Task>(async () => { await InternalAwaitRunning(); }); _taskQueue.Enqueue(newTask); } } /// <summary> /// 执行队列任务 /// </summary> /// <returns></returns> private async Task ExcuteTaskQueue() { try { await _semaphoreSlim.WaitAsync(); var count = _taskQueue.Count; Task<Task> task = null; for (int i = 0; i < count; i++) { // 移出所有的线程,并且只执行最后一个 _taskQueue.TryDequeue(out task); // 移出中间不执行的委托 if (i < count - 1) { _funcQueue.TryDequeue(out Func<Task> func); } } if (task == null) return; task.Start(); await await task; } finally { _semaphoreSlim.Release(); } } #endregion #region 内部运行 /// <summary> /// 执行委托 /// </summary> /// <returns></returns> private async Task InternalAwaitRunning() { if (TryGetNextAwaitTask(out var func)) { await func(); } } /// <summary> /// 获取 /// </summary> /// <param name="func"></param> /// <returns></returns> private bool TryGetNextAwaitTask(out Func<Task> func) { func = null; while (_funcQueue.Count > 0) { //获取并从队列中移除任务 if (_funcQueue.TryDequeue(out func)) { return true; } } return false; } #endregion #region 属性及字段 /// <summary> /// 控制当出现多个任务在队列中时,限制等待上一个任务执行完成才到下一个 /// </summary> private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1); /// <summary> /// 线程队列 /// </summary> private readonly ConcurrentQueue<Task<Task>> _taskQueue = new ConcurrentQueue<Task<Task>>(); /// <summary> /// 委托队列 /// </summary> private readonly ConcurrentQueue<Func<Task>> _funcQueue = new ConcurrentQueue<Func<Task>>(); #endregion } }
上面的异步队列会同步执行,并且自动取消中间未执行的任务。