killapp/Assets/Scripts/Network/RequestQueueManager.cs

285 lines
8.3 KiB
C#
Raw Normal View History

2026-04-16 14:57:19 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace Kill.Network
{
/// <summary>
/// 请求队列管理器 - 管理请求的优先级和并发控制
/// </summary>
public class RequestQueueManager : MonoBehaviour
{
public static RequestQueueManager Instance { get; private set; }
/// <summary>
/// 最大并发请求数
/// </summary>
[SerializeField] private int maxConcurrentRequests = 5;
/// <summary>
/// 请求队列
/// </summary>
private Queue<QueuedRequest> _requestQueue = new Queue<QueuedRequest>();
/// <summary>
/// 正在执行的请求
/// </summary>
private Dictionary<string, QueuedRequest> _activeRequests = new Dictionary<string, QueuedRequest>();
/// <summary>
/// 是否正在处理队列
/// </summary>
private bool _isProcessing = false;
/// <summary>
/// 队列锁
/// </summary>
private readonly object _queueLock = new object();
/// <summary>
/// 请求完成事件
/// </summary>
public event Action<string, bool> OnRequestCompleted;
/// <summary>
/// 队列状态变化事件
/// </summary>
public event Action<int, int> OnQueueStatusChanged;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// 添加请求到队列
/// </summary>
public string Enqueue<T>(Func<Task<HttpResponse<T>>> requestFunc, RequestPriority priority = RequestPriority.Normal, Action<HttpResponse<T>> onComplete = null)
{
var queuedRequest = new QueuedRequest
{
Id = Guid.NewGuid().ToString("N"),
Priority = priority,
CreateTime = DateTime.Now,
ExecuteFunc = async () =>
{
var result = await requestFunc();
onComplete?.Invoke(result);
return result.IsSuccess;
}
};
lock (_queueLock)
{
_requestQueue.Enqueue(queuedRequest);
}
// 按优先级排序
SortQueueByPriority();
OnQueueStatusChanged?.Invoke(_requestQueue.Count, _activeRequests.Count);
// 开始处理队列
if (!_isProcessing)
{
StartCoroutine(ProcessQueue());
}
return queuedRequest.Id;
}
/// <summary>
/// 取消指定请求
/// </summary>
public bool CancelRequest(string requestId)
{
lock (_queueLock)
{
// 检查是否在队列中
var queuedItem = _requestQueue.FirstOrDefault(r => r.Id == requestId);
if (queuedItem != null)
{
var tempQueue = new Queue<QueuedRequest>(_requestQueue.Where(r => r.Id != requestId));
_requestQueue = tempQueue;
OnQueueStatusChanged?.Invoke(_requestQueue.Count, _activeRequests.Count);
return true;
}
// 检查是否正在执行
if (_activeRequests.ContainsKey(requestId))
{
_activeRequests[requestId].CancellationToken?.Cancel();
return true;
}
}
return false;
}
/// <summary>
/// 取消所有请求
/// </summary>
public void CancelAllRequests()
{
lock (_queueLock)
{
// 清空队列
_requestQueue.Clear();
// 取消正在执行的请求
foreach (var request in _activeRequests.Values)
{
request.CancellationToken?.Cancel();
}
}
OnQueueStatusChanged?.Invoke(0, 0);
}
/// <summary>
/// 获取队列状态
/// </summary>
public (int queued, int active) GetQueueStatus()
{
lock (_queueLock)
{
return (_requestQueue.Count, _activeRequests.Count);
}
}
/// <summary>
/// 处理请求队列
/// </summary>
private IEnumerator ProcessQueue()
{
_isProcessing = true;
while (true)
{
QueuedRequest request = null;
lock (_queueLock)
{
if (_requestQueue.Count > 0 && _activeRequests.Count < maxConcurrentRequests)
{
request = _requestQueue.Dequeue();
_activeRequests[request.Id] = request;
}
}
if (request != null)
{
// 执行请求
ExecuteRequest(request);
OnQueueStatusChanged?.Invoke(_requestQueue.Count, _activeRequests.Count);
}
else if (_requestQueue.Count == 0 && _activeRequests.Count == 0)
{
// 队列为空且没有活动请求,退出处理
break;
}
yield return new WaitForSeconds(0.1f);
}
_isProcessing = false;
}
/// <summary>
/// 执行单个请求
/// </summary>
private async void ExecuteRequest(QueuedRequest request)
{
request.CancellationToken = new CancellationTokenSource();
request.Status = RequestStatus.Executing;
request.StartTime = DateTime.Now;
try
{
bool success = await request.ExecuteFunc();
request.Status = success ? RequestStatus.Completed : RequestStatus.Failed;
OnRequestCompleted?.Invoke(request.Id, success);
}
catch (OperationCanceledException)
{
request.Status = RequestStatus.Cancelled;
OnRequestCompleted?.Invoke(request.Id, false);
}
catch (Exception ex)
{
Debug.LogError($"[RequestQueueManager] 请求执行异常: {ex.Message}");
request.Status = RequestStatus.Failed;
OnRequestCompleted?.Invoke(request.Id, false);
}
finally
{
lock (_queueLock)
{
_activeRequests.Remove(request.Id);
}
OnQueueStatusChanged?.Invoke(_requestQueue.Count, _activeRequests.Count);
}
}
/// <summary>
/// 按优先级排序队列
/// </summary>
private void SortQueueByPriority()
{
lock (_queueLock)
{
var sortedList = _requestQueue.OrderByDescending(r => r.Priority)
.ThenBy(r => r.CreateTime)
.ToList();
_requestQueue = new Queue<QueuedRequest>(sortedList);
}
}
/// <summary>
/// 设置最大并发数
/// </summary>
public void SetMaxConcurrentRequests(int max)
{
maxConcurrentRequests = Mathf.Max(1, max);
}
}
/// <summary>
/// 请求状态
/// </summary>
public enum RequestStatus
{
Pending,
Executing,
Completed,
Failed,
Cancelled
}
/// <summary>
/// 队列中的请求
/// </summary>
public class QueuedRequest
{
public string Id { get; set; }
public RequestPriority Priority { get; set; }
public DateTime CreateTime { get; set; }
public DateTime? StartTime { get; set; }
public RequestStatus Status { get; set; } = RequestStatus.Pending;
public Func<Task<bool>> ExecuteFunc { get; set; }
public CancellationTokenSource CancellationToken { get; set; }
}
}