Silverlight并行下载与串行下载

思路清晰后仅仅只需百来行代码便可轻松编写出一套完整的资源动态下载组件- SerialDownloader和ParallelDownloader,它们共用一个完成资源表,且串行下载集成了优先机制(DownloadPriority),并行下载也根据需要封装了并行队列模式(QueueParallelDownloader):

DownloadBase 

    /// <summary>
    /// 下载器基类
    /// </summary>
    public class DownloadBase {

        protected readonly static List<string> loadedUri = new List<string>();

        /// <summary>
        /// 获取已下载完成的地址
        /// </summary>
        public static List<string> LoadedUri { get { return loadedUri; } }

        /// <summary>
        /// 下载失败(错误)次数
        /// </summary>
        public static int Error { get; protected set; }

    }

 

 

ParallelDownloader 

   /// <summary>
    /// 并行资源下载器
    /// </summary>
    public sealed class ParallelDownloader : DownloadBase {

        /// <summary>
        /// 资源下载进度中触发
        /// </summary>
        public event DownloadProgressChangedEventHandler DownloadProgressChanged;

        /// <summary>
        /// 资源下载完成
        /// </summary>
        public event OpenReadCompletedEventHandler OpenReadCompleted;

        /// <summary>
        /// 当前进度百分比
        /// </summary>
        public static int ProgressPercentage { get; private set; }

        readonly static List<string> loadingUri = new List<string>();
        readonly static List<string> waitingUri = new List<string>();
        /// <summary>
        /// 获取当前正在下载的地址
        /// </summary>
        public static List<string> LoadingUri { get { return loadingUri; } }
        /// <summary>
        /// 获取等待下载地址队列
        /// </summary>
        public static List<string> WaitingUri { get { return waitingUri; } }

        /// <summary>
        /// 下载资源文件
        /// </summary>
        /// <param name="uri">资源相对地址<</param>
        /// <param name="userToken">资源参数</param>
        /// <param name="waitingTime">如果正在被下载,等待检测时间(单位:毫秒)</param>
        public void OpenReadAsync(string uri, object userToken, bool isWaiting, int waitingTime) {
            if (loadedUri.Contains(uri)) {
                Download(uri, userToken);
            } else {
                if (loadingUri.Contains(uri)) {
                    //假如该资源正被下载中,则需要等待,每隔1秒检测一次是否已下载完成
                    if (isWaiting) {
                        DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(waitingTime) };
                        EventHandler handler = null;
                        timer.Tick += handler = (s, e) => {
                            if (loadedUri.Contains(uri)) {
                                timer.Stop();
                                timer.Tick -= handler;
                                Download(uri, userToken);
                            }
                        };
                        timer.Start();
                    }
                } else {
                    if (!waitingUri.Contains(uri)) { waitingUri.Add(uri); }
                    loadingUri.Add(uri);
                    Download(uri, userToken);
                }
            }
        }

        /// <summary>
        /// 开始下载
        /// </summary>
        /// <param name="uri">资源相对地址</param>
        /// <param name="userToken">资源参数</param>
        void Download(string uri, object userToken) {
            OpenReadCompletedEventHandler openReadCompletedHandler = null;
            DownloadProgressChangedEventHandler progressChangedHandler = null;
            WebClient webClient = new WebClient();
            webClient.DownloadProgressChanged += progressChangedHandler = (s, e) => {
                ProgressPercentage = e.ProgressPercentage;
                if (DownloadProgressChanged != null) { DownloadProgressChanged(this, e); }
            };
            webClient.OpenReadCompleted += openReadCompletedHandler = (s, e) => {
                WebClient wc = s as WebClient;
                wc.DownloadProgressChanged -= progressChangedHandler;
                wc.OpenReadCompleted -= openReadCompletedHandler;
                if (e.Error != null) {
                    //断网处理,5秒后重试
                    Error++;
                    GlobalMethod.SetTimeout(delegate {
                        Download(uri, userToken);
                    }, 5000);
                } else {
                    waitingUri.Remove(uri);
                    loadingUri.Remove(uri);
                    if (!loadedUri.Contains(uri)) { loadedUri.Add(uri); }
                    if (OpenReadCompleted != null) { OpenReadCompleted(this, e); }
                }
            };
            webClient.OpenReadAsync(new Uri(uri, UriKind.Relative), userToken);
        }
    }

 

SerialDownloader 

    /// <summary>
    /// 下载优先级
    /// </summary>
    public enum DownloadPriority {
        /// <summary>
        /// 最高
        /// </summary>
        Highest = 0,
        /// <summary>
        /// 高
        /// </summary>
        High = 1,
        /// <summary>
        /// 普通
        /// </summary>
        Normal = 2,
        /// <summary>
        /// 低
        /// </summary>
        Low = 3,
        /// <summary>
        /// 最低
        /// </summary>
        Lowest = 4,
    }

    /// <summary>
    /// 串行资源下载器
    /// </summary>
    public class SerialDownloader : DownloadBase {

        /// <summary>
        /// 资源下载完成
        /// </summary>
        public static event OpenReadCompletedEventHandler OpenReadCompleted;

        /// <summary>
        /// 资源下载进度中触发
        /// </summary>
        public static event DownloadProgressChangedEventHandler DownloadProgressChanged;

        /// <summary>
        /// 当前进度百分比
        /// </summary>
        public static int ProgressPercentage { get; private set; }

        static WebClient webClient = null;
        readonly static List<string> loadingUri = new List<string>();
        readonly static List<string> waitingUri = new List<string>();
        /// <summary>
        /// 获取当前正在下载的地址
        /// </summary>
        public static List<string> LoadingUri { get { return loadingUri; } }
        /// <summary>
        /// 获取等待下载地址队列
        /// </summary>
        public static List<string> WaitingUri { get { return waitingUri; } }

        /// <summary>
        /// 为Image图片控件设置图像源
        /// </summary>
        /// <param name="image">目标图片</param>
        /// <param name="uri">图像源地址</param>
        /// <param name="isWaiting">是否等待下载完成后再赋值</param>
        public static void SetImageSource(Image image, string uri, DownloadPriority priority, bool isWaiting) {
            if (loadedUri.Contains(uri)) {
                image.Source = GlobalMethod.GetWebImage(uri);
            } else {
                image.Source = null;
                AddUri(uri, priority);
                if (isWaiting) {
                    DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(2000) };
                    EventHandler handler = null;
                    timer.Tick += handler = (s, e) => {
                        if (loadedUri.Contains(uri)) {
                            timer.Stop();
                            timer.Tick -= handler;
                            image.Source = GlobalMethod.GetWebImage(uri);
                        }
                    };
                    timer.Start();
                }
            }
        }

        /// <summary>
        /// 添加预备下载地址
        /// </summary>
        /// <param name="uri">图像源地址</param>
        public static void AddUri(string uri, DownloadPriority priority) {
            if (!waitingUri.Contains(uri)) { waitingUri.Insert((int)(((int)priority / 4d) * waitingUri.Count), uri); }
            if (loadingUri.Count == 0) {
                webClient = new WebClient();
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
                webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
                webClient.OpenReadAsync(new Uri(GlobalMethod.WebPath(uri), UriKind.Relative), uri);
                loadingUri.Add(uri);
            }
        }

        static void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) {
            WebClient wc = sender as WebClient;
            wc.DownloadProgressChanged -= webClient_DownloadProgressChanged;
            wc.OpenReadCompleted -= webClient_OpenReadCompleted;
            string uri = e.UserState.ToString();
            if (e.Error != null) {
                //断网处理,5秒后重试
                Error++;
                GlobalMethod.SetTimeout(delegate {
                    loadingUri.Remove(uri);
                    AddUri(uri, DownloadPriority.Highest);
                }, 5000);
            } else {
                loadingUri.Remove(uri);
                waitingUri.Remove(uri);
                loadedUri.Add(uri);
                if (waitingUri.Count > 0) { AddUri(waitingUri[0], DownloadPriority.Highest); }
                if (OpenReadCompleted != null) { OpenReadCompleted(sender, e); }
            }
        }

        static void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
            ProgressPercentage = e.ProgressPercentage;
            if (DownloadProgressChanged != null) { DownloadProgressChanged(sender, e); }
        }

    }

 

posted @ 2015-01-30 10:16  童心少年  阅读(222)  评论(0编辑  收藏  举报