我想做一个多线程下载的程序,具体需求是:
有成千上百的文件需要下载,由于每个文件较小,小于2M,所有我想采用每个线程下载一个文件的做法。
但是当我使用线程池把这些任务分配出去后,若用户要点击停止按钮停止下载,或者之后再继续下载,我就不知道该怎么做了。
所以我目前只有直接退出程序这么个笨办法。——因为不知道如何停止和继续线程。
还望高人指点。谢谢。
用 backgroudworker可以满足你的要求,特别是用于暂停和重启这个功能的时候
可参考codeproject上的demo: http://www.codeproject.com/KB/aspnet/ZetaWebSpider.aspx
思维上可以不关注线程 关注任务。线程已经由线程池帮你管理好了
个人认为如果要做到楼主所说的功能 自己弄一个线程 借助线程池只能对其完成情况进行处理 对过程无法干涉·
为你的工作创建一个DownloadWorker类,为其添加 ManualResetEvent 成员变量, 通过ManualResetEvent控制任务运行,暂停,还是退出.
写的一个demo,没仔细测,应该不会有错,希望对你有帮助
using System;
using System.Security.Principal;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
class ADPrincipal
{
static void Main(string[] args)
{
string[] filePah = new string[20];
for(int i=0;i<20;i++)
{
filePah[i]=i+"";
}
DownloadManager manager = new DownloadManager(filePah,5);
string cmd;
while((cmd=Console.ReadLine())!="end")
{
switch (cmd)
{
case "pause":
{
manager.Pause();
break;
}
case "start":
{
manager.Start();
break;
}
case "restart":
{
manager.Restart();
break;
}
case "stop":
{
manager.Stop();
break;
}
case "disposable":
{
manager.Dispose();
break;
}
}
}
}
}
/// <summary>
/// 管理类
/// </summary>
public class DownloadManager:IDisposable
{
private List<string> fileList;
private List<DownloadWork> workList;
private E_State state;
private int perPath;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="filePaths">下载的所有路径</param>
/// <param name="perPath">每个线程需要执行的路径数量</param>
public DownloadManager(string[] filePaths,int perPath)
{
this.state = E_State.Stop;
this.fileList = new List<string>(filePaths.Length);
foreach (string path in filePaths)
{
this.fileList.Add(path);
}
this.perPath = perPath;
}
/// <summary>
/// 执行下载
/// </summary>
/// <param name="perPath">表示每个线程处理几个路径</param>
private void Execute(int perPath)
{
this.state = E_State.Download;
int threadCount = this.fileList.Count % perPath == 0 ? this.fileList.Count / perPath : this.fileList.Count / perPath + 1;
workList = new List<DownloadWork>(7);
DownloadWork work;
Thread thread;
List<string> pathList = new List<string>(perPath);
int j=1,i=1;
foreach(string path in this.fileList)
{
pathList.Add(path);
if (i == j * perPath || i == this.fileList.Count)
{
work = new DownloadWork(pathList.ToArray());
thread = new Thread(new ThreadStart(work.Execute));
work.CurrentThread = thread;
workList.Add(work);
pathList.Clear();
j++;
thread.Start();
}
i++;
}
}
/// <summary>
/// 开始下载
/// </summary>
public void Start()
{
if (this.state != E_State.Stop||this.fileList.Count==0)
{
throw new Exception("已经开始下载或没有路径");
}
this.Execute(this.perPath);
}
/// <summary>
/// 继续下载
/// </summary>
public void Restart()
{
if (this.state != E_State.Pause)
{
throw new Exception("没有暂停下载");
}
this.Execute(this.perPath);
}
/// <summary>
/// 停止整个下载过程
/// </summary>
public void Stop()
{
this.state = E_State.Stop;
foreach (DownloadWork work in workList)
{
work.Abort();
}
this.fileList.Clear();
this.workList.Clear();
}
private void RemovePath(List<string> doneList)
{
foreach (string path in doneList)
{
this.fileList.Remove(path);
}
}
/// <summary>
/// 暂停下载过程
/// </summary>
public void Pause()
{
this.state = E_State.Pause;
foreach (DownloadWork work in this.workList)
{
work.Abort();
//删除已经下载过的路径
this.RemovePath(work.DonePaths);
}
workList.Clear();
}
#region IDisposable 成员
public void Dispose()
{
this.Stop();
}
#endregion
enum E_State
{
Stop,
Download,
Pause
}
}
/// <summary>
/// 执行类
/// </summary>
public class DownloadWork
{
private string[] paths;
public List<string> DonePaths;
private Thread currentThread;
public Thread CurrentThread
{
set
{
this.currentThread = value;
}
}
public DownloadWork(string[] paths)
{
this.paths = paths;
this.DonePaths = new List<string>(paths.Length);
}
public void Execute()
{
//测试用
Thread.Sleep(1000 * 5);
foreach (string path in this.paths)
{
//根据路径来下载,这里用输出代替
Console.WriteLine(path);
//更新已下载
DonePaths.Add(path);
//测试用
Thread.Sleep(1000);
}
}
/// <summary>
/// 终止线程
/// </summary>
public void Abort()
{
try
{
if (this.currentThread.ThreadState != ThreadState.Stopped)
{
this.currentThread.Abort();
}
}
catch
{
}
}
}
mark