项目有这样的需求,
要求窗口加载一揽子图片,为了不让UI阻塞太久,采用异步读取后绑定显示的方案.
图片的下载应该采用并发的过程(等待网络响应会很耗时,一张一张的下载,等待时间太长)
图片的下载不能占用过多的线程数,应有个阀值(图片不是核心业务,不能占用那么多资源)
在图片加载的过程中,如果用户有操作,比如窗口跳转,则未加载完成的图片加载的过程应取消(为了替用户节省流量).
需求就是这么多了,如何实现呢?
思路是这样的,由于需要异步,且需要等待,首先想到使用队列,先让队列排列起来,再定量迭代读取.
因为要涉及异步的取消,想到了用WebClient对象的异步功能, 当然,所以发起异步请求之后的对象我都需要记录,
所以还需要一个list容器.
外部接口是两个参数,url,图片的网址,一个回调,定义了图片下载完成后的操作.
内部的核心流程,
1.将一个图片任务从队列中取出,
2.异步发生此请求,
3.将发起请求的对象放进容器,以备撤销时使用.
撤销的核心流程是.
1.让处理线程停止
2.取消队列中的任务,
3.让等待响应的任务取消.
using System;
using System.Windows;
using System.Windows.Media.Imaging;
using Proj.Interface;
namespace Proj.Common
{
/// <summary>
/// 把网络数据包装为图片源
/// </summary>
public class HttpPicGet : IRevocable
{
public event GetPicCallback OnImageLoadCompleted;
public event Action ProcessCompleted;
/// <summary>
/// 当前正在处理的URL
/// </summary>
public string Url;
HttpResourceGet m_httpGet;
public HttpPicGet()
{
m_httpGet = new HttpResourceGet();
m_httpGet.OnDataStreamGenerated += (stream =>
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
BitmapSource bi = new BitmapImage();
bi.SetSource(stream);
if (OnImageLoadCompleted != null)
{
OnImageLoadCompleted(bi);
}
});
});
m_httpGet.ProcessCompleted += (() =>
{
//Deployment.Current.Dispatcher.BeginInvoke(() =>
// {
if (ProcessCompleted != null)
{
ProcessCompleted();
}
//});
});
}
public void BeginLoadPic(string url)
{
Url = url;
m_httpGet.BeginGetData(url);
}
public void RevokeAsync()
{
m_httpGet.RevokeAsync();
}
}
}