有已知的远程图片URL列表数组(20-30个图片地址),现需要将其下载到本地服务器上,并将保存的图片路径存入数据库中。我现在是单个单个的读取下载,再将其路径保存到数据库.这种方式很慢,在网上看到说多线程、异步下载速度快,由于还不会这技术,现求示例代码
解决方案 »
- 如何将GridView中某列变成不可用状态
- 求[-1,1]的正则表达式
- 请教客户端生成JS语句的问题
- 求高手为什么我总报错需要加上serializable标签?
- 初次使用ajax的简单问题
- 这是怎么回事啊,在线等!!!!!!!!!
- ArrayList为什么没有move方法啊?
- Server.Transfer的使用问题,大虾来帮下忙.
- 请教有在WEb上打开PDF文件,并可以做标签等操作的组件吗?
- 网页上显示word文档问题,急 ,在线等
- "在asp.net自定义控件中"动态添加已存在的控件
- jquery结合ashx实现文件无刷新上传,为什么ashx中获取不到httppostedfile对象。。。
本身支持异步。
....
}它下载一个url文件到本地,然后返回本地保存路径,那么多线程下载并等待所有下载完成的代码就是:var results = yourUrls.AsParallel().Select(url => 下载一个文件(url)).ToArray();
这样得到了一个本地文件路径数组,就是所有并行下载的结果。当然,这是基于.net4.0上的Linq的。
但我用的是.net2.0啊,怎么办呢?
假设你不需要同步等待所有的下载结束,也就是说写一个这样的方法public void 下载一个文件(object url)
{
....
}它下载url并且写入数据库,你只要让他们去并行下载就可以了,不需要等待、监听何时下载完成,那么简单地这样写代码for (int i = 0; i < yourUrls.Length; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(下载一个文件), yourUrls[i]);
}
{
public string result = null;
public AutoResetEvent gate; //用来同步阻塞主线程 public void 下载一个文件(object url)
{
Console.WriteLine("计算{0}", url);
Thread.Sleep(10);
//......你的下载代码,根据this.url下载文件,并且将生成的本地文件路径写入result
result = string.Format("计算{0}的结果", url);
gate.Set();
}
}然后你的主线程需要保存多个任务,以便将来可以遍历其result返回值。同时也要初始化一个AutoResetEvent机制来同步所有任务:AutoResetEvent gate = new AutoResetEvent(false);
下载任务[] tasks = new 下载任务[yourUrls.Length];
for (int i = 0; i < yourUrls.Length; i++)
{
下载任务 task = new 下载任务();
tasks[i] = task;
task.gate = gate;
ThreadPool.QueueUserWorkItem(new WaitCallback(task.下载一个文件), yourUrls[i]);
}
for (int i = 0; i < tasks.Length; i++)
gate.WaitOne();
for (int i = 0; i < tasks.Length; i++)
现在可以遍历tasks[i].result查看每一个本地文件路径;关于AutoResetEvent你自己去看msdn吧。不过设计多线程的程序,需要很多经验,而且真正的难点是当你的程序大了之后很难以测试和调试。最好是使用.net的并行Linq等简单的方法来开发。
test.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Threading;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;/// <summary>
///test 的摘要说明
/// </summary>
public class test
{
public test()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
public string result = null;
public AutoResetEvent gatesss; //用来同步阻塞主线程
public void DownImgUrl(object url)
{ string uriString = url.ToString();
Uri address = new Uri(uriString);
string fileName = "/test/a" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg"; WebClient wc = new WebClient();
try
{
wc.DownloadFile(address, HttpContext.Current.Server.MapPath(fileName));
}
catch (Exception exc)
{
}
finally
{
if (wc != null) wc.Dispose();
} result = string.Format("计算{0}的结果", url);
gatesss.Set();
}
}test.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
string strHTML = "http://hiphotos.baidu.com/lazylazycat/pic/item/038ccf1310818a5b203f2e7f.jpg#http://hiphotos.baidu.com/396058026/pic/item/f5ccf13b864f32af9e3d62d0.jpg";
string[] imgurlAry = strHTML.Split('#');
AutoResetEvent gate = new AutoResetEvent(false);
//下载任务[] tasks = new 下载任务[yourUrls.Length];
test[] tasks = new test[imgurlAry.Length];
for (int i = 0; i < imgurlAry.Length; i++)
{
test task = new test();
tasks[i] = task;
task.gatesss = gate;
ThreadPool.QueueUserWorkItem(new WaitCallback(task.DownImgUrl),imgurlAry[i]);
}
for (int i = 0; i < tasks.Length; i++)
gate.WaitOne();
for (int i = 0; i < tasks.Length; i++)
{
//现在可以遍历tasks[i].result查看每一个本地文件路径;
Response.Write(tasks[i].result+"<br>");
}