csharp/404Lcc/Lcc/Assets/Scripts/Runtime/Core/Manager/Download/DownloadManager.cs

DownloadManager.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace LccModel
{
    public clast DownloadManager : Singleton
    {
        public object lockObject = new object();
        //最大任务数
        public int taskCount = 20;
        //准备队列
        public Queue readyQueue = new Queue();
        //运行
        public Hashtable runnings = new Hashtable();
        //完成列表
        public List completeList = new List();
        //错误列表
        public List errorList = new List();
        public void InitManager()
        {
            ServicePointManager.DefaultConnectionLimit = 100;
            ServicePointManager.ServerCertificateValidationCallback = ServerCertificateValidationCallback;
        }
        public override void Update()
        {
            UpdateTask();
            UpdateProgress();
            UpdateComplete();
            UpdateError();
        }
        public bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            bool isOk = true;
            if (sslPolicyErrors != SslPolicyErrors.None)
            {
                for (int i = 0; i < chain.ChainStatus.Length; i++)
                {
                    if (chain.ChainStatus[i].Status != X509ChainStatusFlags.RevocationStatusUnknown)
                    {
                        chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
                        chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
                        chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                        chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
                        bool chainIsValid = chain.Build((X509Certificate2)certificate);
                        if (!chainIsValid)
                        {
                            isOk = false;
                        }
                    }
                }
            }
            return isOk;
        }
        public void DownloadAsync(DownloadData downloadData)
        {
            DownloadFile downloadFile = new DownloadFile(downloadData);
            lock (lockObject)
            {
                readyQueue.Enqueue(downloadFile);
            }
            if (runnings.Count >= taskCount) return;
            Task task = Task.Run(DownloadTask);
            task.Start();
        }
        public void DownloadAsync(DownloadData[] downloadDatas)
        {
            foreach (DownloadData item in downloadDatas)
            {
                DownloadAsync(item);
            }
        }
        public void DownloadTask()
        {
            lock (lockObject)
            {
                runnings.Add(Thread.CurrentThread, null);
            }
            while (true)
            {
                DownloadFile downloadFile = null;
                lock (lockObject)
                {
                    if (readyQueue.Count > 0)
                    {
                        downloadFile = readyQueue.Dequeue();
                        runnings[Thread.CurrentThread] = downloadFile;
                    }
                }
                if (downloadFile == null) break;
                downloadFile.Download();
                if (downloadFile.state == DownloadState.Complete)
                {
                    lock (lockObject)
                    {
                        completeList.Add(downloadFile.downloadData);
                        runnings[Thread.CurrentThread] = null;
                    }
                }
                else if (downloadFile.state == DownloadState.Error)
                {
                    lock (lockObject)
                    {
                        if (downloadFile.count == 5)
                        {
                            errorList.Add(downloadFile);
                        }
                        else
                        {
                            readyQueue.Enqueue(downloadFile);
                        }
                    }
                    break;
                }
                else
                {
                    break;
                }
            }
        }
        public void UpdateTask()
        {
            if (readyQueue.Count == 0 && runnings.Count == 0) return;
            lock (lockObject)
            {
                List threadList = new List();
                foreach (DictionaryEntry item in runnings)
                {
                    //卡死线程
                    if (!((Thread)item.Key).IsAlive)
                    {
                        if (item.Value != null)
                        {
                            readyQueue.Enqueue((DownloadFile)item.Value);
                        }
                        threadList.Add((Thread)item.Key);
                    }
                }
                foreach (Thread item in threadList)
                {
                    item.Abort();
                    runnings.Remove(item);
                }
            }
            if (NetworkUtil.CheckNetwork())
            {
                if (runnings.Count < taskCount && readyQueue.Count > 0)
                {
                    Task task = Task.Run(DownloadTask);
                    task.Start();
                }
            }
        }
        public void UpdateProgress()
        {
            if (runnings.Count == 0) return;
            List downloadFileList = new List();
            lock (lockObject)
            {
                foreach (DownloadFile item in runnings.Values)
                {
                    if (item != null)
                    {
                        downloadFileList.Add(item);
                    }
                }
            }
            foreach (DownloadFile item in downloadFileList)
            {
                item.downloadData.ProgressExcute(item.currentSize, item.downloadData.size);
            }
        }
        public void UpdateComplete()
        {
            if (completeList.Count == 0) return;
            List downloadDataList = new List();
            lock (lockObject)
            {
                downloadDataList.AddRange(completeList.ToArray());
                completeList.Clear();
            }
            foreach (DownloadData item in downloadDataList)
            {
                item.ProgressExcute(item.size, item.size);
                item.CompleteExcute();
            }
        }
        public void UpdateError()
        {
            if (errorList.Count == 0) return;
            List downloadFileList = new List();
            lock (lockObject)
            {
                downloadFileList.AddRange(errorList.ToArray());
                errorList.Clear();
            }
            foreach (DownloadFile item in downloadFileList)
            {
                item.downloadData.ErrorExcute(item.error);
            }
        }
    }
}