/// <summary>
/// 異步任務隊列
/// </summary>
public class AsyncTaskQueue : IDisposable
{
/// <summary>
/// 異步任務隊列
/// </summary>
public AsyncTaskQueue()
{
_autoResetEvent = new AutoResetEvent(false);
_thread = new Thread(InternalRunning) { IsBackground = true };
_thread.Start();
}
#region 執行
/// <summary>
/// 執行異步操作
/// </summary>
/// <typeparam name="T">返回結果類型</typeparam>
/// <param name="func">異步操作</param>
/// <returns>isInvalid:異步操作是否有效;result:異步操作結果</returns>
public async Task<(bool isInvalid, T reslut)> ExecuteAsync<T>(Func<Task<T>> func)
{
var task = GetExecutableTask(func);
var result = await await task;
if (!task.IsInvalid)
{
result = default(T);
}
return (task.IsInvalid, result);
}
/// <summary>
/// 執行異步操作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func"></param>
/// <returns></returns>
public async Task<bool> ExecuteAsync<T>(Func<Task> func)
{
var task = GetExecutableTask(func);
await await task;
return task.IsInvalid;
}
#endregion
#region 添加任務
/// <summary>
/// 獲取待執行任務
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
private AwaitableTask GetExecutableTask(Action action)
{
var awaitableTask = new AwaitableTask(new Task(action));
AddPenddingTaskToQueue(awaitableTask);
return awaitableTask;
}
/// <summary>
/// 獲取待執行任務
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="function"></param>
/// <returns></returns>
private AwaitableTask<TResult> GetExecutableTask<TResult>(Func<TResult> function)
{
var awaitableTask = new AwaitableTask<TResult>(new Task<TResult>(function));
AddPenddingTaskToQueue(awaitableTask);
return awaitableTask;
}
/// <summary>
/// 添加待執行任務到隊列
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
private void AddPenddingTaskToQueue(AwaitableTask task)
{
//添加隊列,加鎖。
lock (_queue)
{
_queue.Enqueue(task);
//開始執行任務
_autoResetEvent.Set();
}
}
#endregion
#region 內部運行
private void InternalRunning()
{
while (!_isDisposed)
{
if (_queue.Count == 0)
{
//等待后續任務
_autoResetEvent.WaitOne();
}
while (TryGetNextTask(out var task))
{
//如已從隊列中刪除
if (task.NotExecutable) continue;
if (UseSingleThread)
{
task.RunSynchronously();
}
else
{
task.Start();
}
}
}
}
/// <summary>
/// 上一次異步操作
/// </summary>
private AwaitableTask _lastDoingTask;
private bool TryGetNextTask(out AwaitableTask task)
{
task = null;
while (_queue.Count > 0)
{
//獲取并從隊列中移除任務
if (_queue.TryDequeue(out task) && (!AutoCancelPreviousTask || _queue.Count == 0))
{
//設置進行中的異步操作無效
_lastDoingTask?.MarkTaskValid();
_lastDoingTask = task;
return true;
}
//并發操作,設置任務不可執行
task.SetNotExecutable();
}
return false;
}
#endregion
#region dispose
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 析構任務隊列
/// </summary>
~AsyncTaskQueue() => Dispose(false);
private void Dispose(bool disposing)
{
if (_isDisposed) return;
if (disposing)
{
_autoResetEvent.Dispose();
}
_thread = null;
_autoResetEvent = null;
_isDisposed = true;
}
#endregion
#region 屬性及字段
/// <summary>
/// 是否使用單線程完成任務.
/// </summary>
public bool UseSingleThread { get; set; } = true;
/// <summary>
/// 自動取消以前的任務。
/// </summary>
public bool AutoCancelPreviousTask { get; set; } = false;
private bool _isDisposed;
private readonly ConcurrentQueue<AwaitableTask> _queue = new ConcurrentQueue<AwaitableTask>();
private Thread _thread;
private AutoResetEvent _autoResetEvent;
#endregion