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); }
        }

    }
时间: 2024-11-04 17:31:55

Silverlight并行下载与串行下载的相关文章

Java8新特性 - 并行流与串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性地通过parallel()和sequential()在并行流和顺序流之间进行切换. 在了解并行流之前,我们首先需要了解Fork/Join框架 Fork/Join框架 Fork/Join框架:在必要的情况下,将一个大任务进行拆分(fork)成若干个小任务(拆到不可在拆时),在将一个个的小任务运算的结果进行汇总(join). Fo

for循环、并行流、串行流效率比较

User类 import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor; @Builder@Data@AllArgsConstructor@NoArgsConstructorpublic class User { int id; String name; int sex; int age; } 测试类 import org.springframe

【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例(转载)

(1)GCD实现的同步异步.串行并行. ——同步sync应用场景:用户登录,利用阻塞 ——串行异步应用场景:下载等耗时间的任务 /** * 因为是异步,所以开通了子线程,但是因为是串行队列,所以只需要开通1个子线程(2),它们在子线程中顺序执行.最常用. */ -(void)gcdDemo1{ dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL); for

GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例

转:http://www.tuicool.com/articles/NVVnMn (1)GCD实现的同步异步.串行并行. ——同步sync应用场景:用户登录,利用阻塞 ——串行异步应用场景:下载等耗时间的任务 /** * 因为是异步,所以开通了子线程,但是因为是串行队列,所以只需要开通1个子线程(2),它们在子线程中顺序执行.最常用. */ -(void)gcdDemo1{ dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gc

IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)

进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispatch_queue_t,队列名称在调试时辅助,无论什么队列和任务,线程的创建和回收不需要程序员操作,有队列负责. 串行队列:队列中的任务只会顺序执行(类似跑步) dispatch_queue_t q = dispatch_queue_create(“....”, DISPATCH_QUEUE_SER

同步 ,异步,并发/并行,串行

同步:多个任务情况下,一个任务A执行结束,才可以执行另一个任务B.只存在一个线程. 异步:多个任务情况下,一个任务A正在执行,同时可以执行另一个任务B.任务B不用等待任务A结束才执行.存在多条线程. 接下来分析一下并行/并发,串行.很多人大概会混淆这些概念. 并发和并行其实是异步队列实现的两种形式.并行其实是真正的异步,多核CUP可以同时开启多条线程供多个任务同时执行,互补干扰,如上图的并行,其实和异步图例一样.但是并发就不一样了,是一个伪异步.在单核CUP中只能有一条线程,但是又想执行多个任务

FS BPM 业余研发(用户详细操作手册--单人串行/并行)之 深圳分公司技术部请假审批流程

1.FS BPM 简介 BPM软件中BPM是英文字母缩写,大致有二个意思.第一.Business Process Management,即业务流程管理,是一套达成企业各种业 务环节整合的全面管理模式.第二.Business Process Modeling,即业务流程建模,是对业务流程进行表述的方式,它是过程分析与重组的 重要基础. 如果再不了解请自行百度了,本人在这里就不再详细介绍了. 2.FS BPM 系统开发介绍 FS BPM于2017年1月开始进行开发.其中经历多个难题.用高性能机制解决

串行队列、并行队列、同步、异步

进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispatch_queue_t,队列名称在调试时辅助,无论什么队列和任务,线程的创建和回收不需要程序员操作,有队列负责. 串行队列:队列中的任务只会顺序执行(类似跑步) dispatch_queue_t q = dispatch_queue_create(“....”, dispatch_queue_ser

串行除法与并行除法

以下内容摘自<步步惊芯--软核处理器内部设计分析>一书 串行除法与并行除法 8.2.1 串行除法 OR1200中使用的串行除法算法是"试商法".设被除数是m,除数是n,商保存在s中,被除数的位数是k,其计算步骤如下(为了便于说明,在此处所有数据的最低位称之为第1位,而不称为第0位): (1)取出被除数的最高位m[k],使用被除数的最高位减去除数n,如果结果大于等于0,则商的s[k]为1,反之为0. (2)如果上一步得出的结果是0,表示当前的被减数小于除数,则取出被除数m[k