using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using UnityEngine; /// /// 多线程任务调度系统 /// public class TaskSchedulerManager : MBSingletonManager { /// /// 任务返回主线程的队列 /// private ConcurrentQueue mainThreadQueue = new ConcurrentQueue(); /// /// 用于管理多线程任务 /// private Dictionary tasks = new Dictionary(); /// /// 用于管理任务的 CancellationTokenSource /// private Dictionary taskCancellationTokens = new Dictionary(); /// /// 任务ID计数器 /// private int taskIdCounter = 0; private void Update() { // 在主线程中执行任务队列 while (mainThreadQueue.TryDequeue(out var task)) { task.Invoke(); } // 清理已完成的任务 List completedTaskIds = new List(); foreach (var taskEntry in tasks) { if (taskEntry.Value.IsCompleted) { completedTaskIds.Add(taskEntry.Key); } } foreach (var taskId in completedTaskIds) { tasks.Remove(taskId); taskCancellationTokens.Remove(taskId); } } /// /// 启动一个多线程任务 /// /// 异步任务函数 /// 任务完成后的回调 /// 任务ID public int RunTask(Func taskFunc, Action onCompleted = null) { int taskId = taskIdCounter++; var cts = new CancellationTokenSource(); taskCancellationTokens[taskId] = cts; var task = Task.Run(async () => { try { await taskFunc(cts.Token); if (onCompleted != null) { mainThreadQueue.Enqueue(onCompleted); } } catch (OperationCanceledException) { Debug.Log($"任务 {taskId} 已被取消"); } catch (Exception ex) { Debug.LogError($"任务 {taskId} 执行失败: {ex.Message}"); } }, cts.Token); tasks[taskId] = task; return taskId; } /// /// 取消单个任务 /// /// 任务ID public void CancelTask(int taskId) { if (taskCancellationTokens.TryGetValue(taskId, out var cts)) { cts.Cancel(); Debug.Log($"任务 {taskId} 已取消"); } else { Debug.LogWarning($"未找到任务 {taskId}"); } } /// /// 等待所有任务完成 /// public void WaitForAllTasks() { Task.WhenAll(tasks.Values).Wait(); } /// /// 取消所有任务 /// public void CancelAllTasks() { foreach (var cts in taskCancellationTokens.Values) { cts.Cancel(); } Debug.Log("所有任务已取消"); } /// /// 清理所有任务 /// public void ClearAllTasks() { CancelAllTasks(); tasks.Clear(); taskCancellationTokens.Clear(); mainThreadQueue.Clear(); } }