Files
Main/Assets/Plugins/References/FuncellUpdate/UpdateModel/Download/BackDownload/ThreadPool.cs
2025-01-25 04:38:09 +08:00

252 lines
6.7 KiB
C#

namespace Thousandto.Update.Download
{
using Thousandto.Update.Delegate;
using Thousandto.Update.Log;
using System;
using System.Collections.Generic;
using System.Threading;
public class ThreadPool<T> where T: new()
{
private ThreadPoolAction<T> _action;
private DataPool<T> _dataPool;
private MyThread _highPriorityThread;
protected object _lockObj;
private bool _pause;
private bool _stop;
private ManualResetEvent _threadManger;
private List<MyThread> _threadQueue;
public ThreadPool(int maxThreadCount, ThreadPoolAction<T> action)
{
_threadQueue = new List<MyThread>();
_dataPool = new DataPool<T>();
_lockObj = new object();
_stop = false;
_action = action;
_threadManger = new ManualResetEvent(false);
for (int i = 0; i < maxThreadCount; i++)
{
MyThread item = new MyThread(i);
item.Name = "download thread: " + i;
if (_highPriorityThread == null)
{
_highPriorityThread = item;
_highPriorityThread.Start(new ThreadStart(HighPriorityThreadFunc), ThreadPriority.Normal);
}
else
{
item.Start(new ThreadStart(ThreadFunc), ThreadPriority.BelowNormal);
}
_threadQueue.Add(item);
}
UpdateLog.WARN_LOG("Init ThreadPool");
}
internal void AddData(T data, DataLevel level, bool fail = false)
{
_dataPool.AddData(data, level, fail);
if (!_pause)
{
_threadManger.Set();
}
if (level == DataLevel.High)
{
_highPriorityThread.Resume();
}
}
internal void AddFailData(T data)
{
_dataPool.AddFailData(data);
}
internal void ClearData(DataLevel level)
{
_dataPool.ClearQueue(level);
}
private void Dowork(T fileData)
{
if (_action != null)
{
_action(fileData);
}
}
private T GetTask()
{
return PopData();
}
private void Join()
{
for (int i = 0; i < _threadQueue.Count; i++)
{
}
_dataPool.Clear();
_threadQueue.Clear();
}
/// <summary>
/// 暂停普通下载队列,除了高优先级队列,其他队列都暂停
/// </summary>
public void Pause()
{
_pause = true;
_threadManger.Reset();
}
/// <summary>
/// 暂停指定下载队列
/// </summary>
/// <param name="level"></param>
internal void PauseLevel(DataLevel level)
{
_dataPool.PauseLevel(level);
}
/// <summary>
/// 恢复指定下载队列
/// </summary>
/// <param name="level"></param>
internal void ResumeLevel(DataLevel level)
{
_dataPool.ResumeLevel(level);
}
public virtual T PopData()
{
return _dataPool.PopData();
}
/// <summary>
/// 恢复所有下载队列
/// </summary>
public void Resume()
{
_pause = false;
_threadManger.Set();
_highPriorityThread.Resume();
}
/// <summary>
/// 是否暂停中,除了高优先级队列,其他队列都暂停
/// </summary>
/// <returns></returns>
public bool IsPaused()
{
return _pause;
}
/// <summary>
/// 是否静默更新暂停中
/// </summary>
/// <returns></returns>
internal bool IsBaseResPaused()
{
return _dataPool.IsBaseResPaused();
}
/// <summary>
/// 是否当前场景暂停中
/// </summary>
/// <returns></returns>
internal bool IsCurScenePaused()
{
return _dataPool.IsCurScenePaused();
}
/// <summary>
/// 获取对应下载队列中数据个数
/// </summary>
/// <param name="level"></param>
/// <returns></returns>
internal int GetDataCount(DataLevel level)
{
return _dataPool.GetDataCount(level);
}
private void Stop()
{
_stop = true;
Resume();
}
/// <summary>
/// 高优先级下载
/// </summary>
private void HighPriorityThreadFunc()
{
while (!_stop)
{
if (_dataPool.GetHighPriorityQueueCount() == 0)
{
UpdateLog.DEBUG_LOG("High Thread pause : " + Thread.CurrentThread.Name);
_highPriorityThread.Pause();
}
T task = GetTask();
if (task == null)
{
if (!_stop)
{
UpdateLog.DEBUG_LOG("High Thread pause1 : " + Thread.CurrentThread.Name);
_highPriorityThread.Pause();
}
}
else
{
Dowork(task);
}
}
UpdateLog.DEBUG_LOG("High Thread abort: " + Thread.CurrentThread.Name);
}
/// <summary>
/// 普通资源下载
/// </summary>
private void ThreadFunc()
{
while (!_stop)
{
if (_pause)
{
UpdateLog.DEBUG_LOG("Normal Thread pause : " + Thread.CurrentThread.Name);
_threadManger.Reset();
_threadManger.WaitOne();
}
T task = GetTask();
if (task == null)
{
UpdateLog.DEBUG_LOG("Normal Thread pause1 : " + Thread.CurrentThread.Name);
if (!_stop)
{
_threadManger.Reset();
_threadManger.WaitOne();
}
}
else
{
Dowork(task);
}
}
UpdateLog.DEBUG_LOG("Normal Thread abort: " + Thread.CurrentThread.Name);
}
public void WaitForFinish()
{
Stop();
Join();
}
public object Locker
{
get
{
return _lockObj;
}
}
}
}