zoukankan      html  css  js  c++  java
  • unity http multithread download

    base http protocal  & Loom 

    
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Text;
    using UnityEngine;
    using System.IO;
    using System.Threading;

    
    

    public class HttpDownloadItem
    {
    const int MBYTES = 1024 * 1024;

    
    

    public enum State
    {
    INITIAL,
    DOWNLOADING,
    ERROR,
    COMPLETE
    }

    
    

    public string m_URL;
    public string m_StoragePath;
    public State m_State;
    public long m_FileLength;

    
    

    int m_DownloadedBytesCount;
    long m_ThreadsPreDownloadBytes;
    FileStream m_FileStream;

    
    

    object m_WriteLock;
    bool m_Disposed;
    long m_StartIndex;
    int m_ThreadsNum;
    AutoResetEvent m_AutoReset = new AutoResetEvent(false);

    
    

    public HttpDownloadItem(string url, string storagePath)
    {
    m_URL = url;
    m_StoragePath = storagePath;
    m_State = State.INITIAL;
    m_WriteLock = new object();
    }

    
    

    public void Reset()
    {
    m_State = State.INITIAL;
    }

    
    

    public void Start()
    {
    m_State = State.DOWNLOADING;
    Loom.RunAsync(() => {
    InitDownloadLength();
    StartDownload();
    });
    }

    
    

    public void Dispose()
    {
    m_Disposed = true;
    if (m_FileStream != null)
    m_FileStream.Close();
    }

    
    

    void InitDownloadLength()
    {
    try
    {
    var request = WebRequest.GetHttpWebRequest(m_URL);
    request.Timeout = 10000;
    request.SendChunked = false;
    request.Method = WebRequestMethods.Http.Head;
    var response = request.GetResponse();
    m_FileLength = response.ContentLength;
    m_FileStream = File.Open(m_StoragePath, FileMode.OpenOrCreate, FileAccess.Write);
    m_FileStream.SetLength(0);
    response.Close();
    request.Abort();
    }
    catch (Exception e)
    {
    m_State = State.ERROR;
    MainThreadLog(e.ToString());
    m_FileStream.Close();
    throw e;
    }
    }

    
    

    void StartDownload()
    {
    while (m_FileLength - m_ThreadsPreDownloadBytes > 0)
    {
    if (m_Disposed)
    break;

    
    

    if (Loom.Current.IsThreadsMax())
    {
    if (m_ThreadsNum > 0)
    m_AutoReset.WaitOne();

    
    

    continue;
    }

    
    

    long length = 0;
    var remain = m_FileLength - m_ThreadsPreDownloadBytes;
    if (remain > MBYTES)
    {
    m_ThreadsPreDownloadBytes += MBYTES;
    length = MBYTES;
    }
    else
    {
    m_ThreadsPreDownloadBytes += remain;
    length = remain;
    }

    
    

    var start = m_StartIndex;
    Interlocked.Increment(ref m_ThreadsNum);
    Loom.RunAsync(() => Down((int)start, (int)length));
    m_StartIndex += length;
    }

    
    

    while (m_ThreadsNum > 0)
    continue;

    
    

    CompleteDownload();
    }

    
    

    void Down(int startIndex, int length, int retryTime = 0)
    {
    if (retryTime > 0)
    MainThreadLog("下载线程重试 : " + retryTime.ToString());

    
    

    if (retryTime == 3)
    {
    m_State = State.ERROR;
    throw new Exception("one thread download three times fail.");
    }

    
    

    try
    {
    if (m_Disposed)
    return;

    
    

    var request = WebRequest.GetHttpWebRequest(m_URL);
    request.Timeout = 10000;
    request.AddRange(startIndex, startIndex + length - 1);
    request.ServicePoint.ConnectionLimit = int.MaxValue;
    request.SendChunked = false;
    request.Method = WebRequestMethods.Http.Get;
    var response = request.GetResponse();
    var stream = response.GetResponseStream();
    stream.ReadTimeout = 10000;
    var buffer = new byte[MBYTES];
    var count = 0;
    var totalCount = 0;
    while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
    {
    lock (m_WriteLock)
    {
    m_FileStream.Seek(startIndex + totalCount, SeekOrigin.Begin);
    m_FileStream.Write(buffer, 0, count);
    m_DownloadedBytesCount += count;
    }

    
    

    UnityEngine.Debug.LogError((float)m_DownloadedBytesCount / (MBYTES));
    totalCount += count;
    if (totalCount >= length)
    break;
    }

    
    

    stream.Close();
    response.Close();
    request.Abort();
    }
    catch (Exception e)
    {
    MainThreadLog(e.ToString());
    Down(startIndex, length, retryTime + 1);
    }
    finally
    {
    m_AutoReset.Set();
    Interlocked.Decrement(ref m_ThreadsNum);
    }
    }

    
    

    void CompleteDownload()
    {
    try
    {
    m_FileStream.Flush();

    
    

    if (m_DownloadedBytesCount == m_FileLength)
    {
    m_State = State.COMPLETE;
    UnityEngine.Debug.Log("Download OK : " + m_URL);
    }
    else
    {
    UnityEngine.Debug.Log("Download ERROR : " + m_URL);
    m_State = State.ERROR;
    }
    }
    finally
    {
    Dispose();
    }
    }

    
    

    void MainThreadLog(string s)
    {
    Loom.QueueOnMainThread(() => {
    UnityEngine.Debug.LogError(string.Format("download exception : {0} URL : {1}", s, m_URL));
    });
    }
    }

    
    

    public class HttpDownload
    {
    Dictionary<string, string> m_URLAndPaths;
    Queue<HttpDownloadItem> m_DownloadQueue;
    Action m_OnComplete;
    Action m_OnError;
    bool m_Disposed;

    
    

    public HttpDownload(Dictionary<string, string> urlAndPaths, Action onComplete, Action onError)
    {
    m_URLAndPaths = urlAndPaths;
    m_DownloadQueue = new Queue<HttpDownloadItem>();
    foreach (var pair in urlAndPaths)
    {
    var item = new HttpDownloadItem(pair.Key, pair.Value);
    m_DownloadQueue.Enqueue(item);
    }

    
    

    m_OnComplete = onComplete;
    m_OnError = onError;
    }

    
    

    ~HttpDownload()
    {
    Dispose();
    }

    
    

    public void Dispose()
    {
    m_Disposed = true;
    m_URLAndPaths = null;
    }

    
    

    public void Retry()
    {
    if (m_DownloadQueue.Count <= 0)
    return;

    
    

    var item = m_DownloadQueue.Peek();
    item.Reset();
    Run();
    }

    
    

    public void Run()
    {
    Loom.RunAsync(() => {
    while (true)
    {
    // 队列为空,结束下载
    if (m_DownloadQueue.Count == 0)
    {
    Loom.QueueOnMainThread(() => {
    if (m_OnComplete != null)
    m_OnComplete();
    });
    break;
    }

    
    

    if (m_Disposed)
    {
    foreach (var t in m_DownloadQueue)
    t.Dispose();

    
    

    break;
    }

    
    

    var item = m_DownloadQueue.Peek();
    switch (item.m_State)
    {
    case HttpDownloadItem.State.INITIAL:
    item.Start();
    break;
    case HttpDownloadItem.State.COMPLETE:
    m_DownloadQueue.Dequeue();
    break;
    case HttpDownloadItem.State.ERROR:
    Loom.QueueOnMainThread(()=> {
    if (m_OnError != null)
    m_OnError();
    });
    Debug.LogError("One Download Item Error");
    return;
    }
    }
    });
    }
    }

     
  • 相关阅读:
    对比度受限的自适应直方图均衡化(CLAHE)
    双边滤波
    快速高斯滤波
    积分图像的应用(二):非局部均值去噪(NL-means)
    非局部均值去噪(NL-means)
    积分图像的应用(一):局部标准差 分类: 图像处理 Matlab 2015-06-06 13:31 137人阅读 评论(0) 收藏
    积分图像 分类: 图像处理 Matlab 2015-06-06 10:30 149人阅读 评论(0) 收藏
    双边滤波与引导滤波 分类: 图像处理 2015-04-29 14:52 48人阅读 评论(0) 收藏
    UE4射击小游戏原型
    UnrealEngine4 尝鲜
  • 原文地址:https://www.cnblogs.com/liucUP/p/12803003.html
Copyright © 2011-2022 走看看