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); }
} }
Silverlight并行下载与串行下载的更多相关文章
- 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...
- 【Java8新特性】关于并行流与串行流,你必须掌握这些!!
写在前面 提到Java8,我们不得不说的就是Lambda表达式和Stream API.而在Java8中,对于并行流和串行流同样做了大量的优化.对于并行流和串行流的知识,也是在面试过程中,经常被问到的知 ...
- JDK8--07:并行流与串行流
JDK8中,提供了并行流和串行流,使用parallel()和sequential()来处理,parallel()为并行流sequential()为串行流,两者可以相互转换,以最后一个为准 LongSt ...
- Java8的新特性--并行流与串行流
目录 写在前面 Fork/Join框架 Fork/Join框架与传统线程池的区别 传统的线程池 Fork/Join框架 Fork/Join框架的使用 Java8中的并行流 写在前面 我们都知道,在开发 ...
- Java8新特性 并行流与串行流 Fork Join
并行流就是把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流. Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作. Stream API 可以声明性地通过 para ...
- 三、并行流与串行流 Fork/Join框架
一.并行流概念: 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性的通过pa ...
- Java8新特性 - 并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性地通过parallel()和 ...
- GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例
转:http://www.tuicool.com/articles/NVVnMn (1)GCD实现的同步异步.串行并行. ——同步sync应用场景:用户登录,利用阻塞 ——串行异步应用场景:下载等耗时 ...
- 【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例
(1)GCD实现的同步异步.串行并行. --同步sync应用场景:用户登录,利用堵塞 --串行异步应用场景:下载等耗时间的任务 /** * 由于是异步.所以开通了子线程.可是由于是串行队列,所以仅仅须 ...
随机推荐
- iOS 9适配技巧(更新版)
转自: http://www.cocoachina.com/ios/20150929/13598.html 中文快速导航: 1.iOS9网络适配_ATS:改用更安全的HTTPS(见Demo1) i ...
- 【C#】开发可以可视化操作的windows服务
使用C#开发自定义windows服务是一件十分简单的事.那么什么时候,我们需要自己开发windows服务呢,就是当我们需要计算机定期或者一直执行我们开发的某些程序的时候.这里我以一个WCF的监听服务为 ...
- log4j学习笔记
在java文件中导入包: import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; 在所使 ...
- visual assist常用快捷键
转自http://my.oschina.net/u/211101/blog/127822 一些打开啊新建就不说了…… //先来个我自己最喜欢的,经常不用,老忘记,以前eclipse最喜欢这个快捷键了 ...
- 转载:MyEclipse启动Tomcat缓慢的原因及解决办法
转自linux公社 不知道朋友们是否有一种烦恼:有时候使用MyEclipse启动Tomcat十分缓慢,可能在几分钟前20秒以内,但现在却需要200秒开外:其间内存和CPU都被占用地厉害,而控制台的输出 ...
- Linux 终端颜色高亮
昨天在改一些东西时,不小心将root下的一些配置文件删掉了.导致启动终端后,字完全一个颜色,没有区分.在网上找到的都是 改整体颜色的.但实际上这时应该搜Linux终端高亮才能找到解决办法.在这里再列出 ...
- Javascript 可同时变大变宽等一系列效果运动框架——逐行分析代码,让你轻松了解运动的原理
等待已久的可变大,变宽 等一系列效果运动框架出炉了,现在还是个初级版本,能满足需求.我们看看是如何实现的. 我们知道在Javascript 中 ‘.’等同于 ‘[]’ 例如: oDiv.style.h ...
- DenyHosts 安装及配置详解
DenyHosts是Python语言写的一个程序,它会分析sshd的日志文件(/var/log/secure),当发现重 复的攻击时就会记录IP到/etc/hosts.deny文件,从而达到自动屏IP ...
- ssh 应用
SSH反向连接及Autossh ssh 隧道: http://www.cnblogs.com/robinyjj/archive/2008/11/02/1325018.html This guy wri ...
- openstack之horizon源码分析
一.基础准备: Horizon是基于django webframework开发的标准的Python wsgi程序,django的设计专注于代码的高度可重用,信奉DRY原则,一切面向对象,而Horizo ...