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();
}
}