285 lines
8.3 KiB
C#
285 lines
8.3 KiB
C#
|
|
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; }
|
||
|
|
}
|
||
|
|
}
|