在我的下载程序中添加暂停和继续功能

2 c# multithreading download webclient-download

我正在用C#创建一个下载程序.我正在使用WebClient类.要在按钮上暂停下载,我可以考虑使用Thread.所以当我创建线程并将其附加到我的文件下载如下

WebClient web = new WebLCient();
Thread dwnd_thread = new Thread(Program.web.DownloadFileAsync(new Uri(Program.src), Program.dest));
Run Code Online (Sandbox Code Playgroud)

它给了我以下错误:"'System.Threading.Thread.Thread(System.Threading.ThreadStart)'的最佳重载方法匹配'有一些无效的参数"和"Argument'1':无法从'void'转换为' System.Threading.ThreadStart'".

然后我想如果我暂停我的系统主线程然后它可以阻止我在下面的代码行使用的整个过程

System.Threading.Thread.Sleep(100);
Run Code Online (Sandbox Code Playgroud)

但它什么都不做.有人可以告诉我什么是更好的暂停/下载方法以及如何使用线程暂停我的下载过程.

ebb*_*ebb 8

由于没有标准的暂停/恢复下载请求的方法,您必须实现自己的机制.下面是一段代码,包含这种机制的外观示例.该类FileDownload有3个参数:

  • source - url到该文件,下载.

  • destination - 保存文件的位置.

  • chunkSize - 在检查是暂停还是继续下载之前要读取的字节数.


public class FileDownload
{
    private volatile bool _allowedToRun;
    private string _source;
    private string _destination;
    private int _chunkSize;

    private Lazy<int> _contentLength;

    public int BytesWritten { get; private set; }
    public int ContentLength { get { return _contentLength.Value; } }

    public bool Done { get { return ContentLength == BytesWritten; } }

    public FileDownload(string source, string destination, int chunkSize)
    {
        _allowedToRun = true;

        _source = source;
        _destination = destination;
        _chunkSize = chunkSize;
        _contentLength = new Lazy<int>(() => Convert.ToInt32(GetContentLength()));

        BytesWritten = 0;
    }

    private long GetContentLength()
    {
        var request = (HttpWebRequest)WebRequest.Create(_source);
        request.Method = "HEAD";

        using (var response = request.GetResponse())
            return response.ContentLength;
    }

    private async Task Start(int range)
    {
        if (!_allowedToRun)
            throw new InvalidOperationException();

        var request = (HttpWebRequest)WebRequest.Create(_source);
        request.Method = "GET";
        request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
        request.AddRange(range);

        using (var response = await request.GetResponseAsync())
        {
            using (var responseStream = response.GetResponseStream())
            {
                using (var fs = new FileStream(_destination, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
                {
                    while (_allowedToRun)
                    {
                        var buffer = new byte[_chunkSize];
                        var bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                        if (bytesRead == 0) break;

                        await fs.WriteAsync(buffer, 0, bytesRead);
                        BytesWritten += bytesRead;
                    }

                    await fs.FlushAsync();
                }
            }
        }
    }

    public Task Start()
    {
        _allowedToRun = true;
        return Start(BytesWritten);
    }

    public void Pause()
    {
        _allowedToRun = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

static void Main(string[] args)
{
    var fw = new FileDownload("http://download.microsoft.com/download/E/E/2/EE2D29A1-2D5C-463C-B7F1-40E4170F5E2C/KinectSDK-v1.0-Setup.exe", @"D:\KinetSDK.exe", 5120);

    // Display progress...
    Task.Factory.StartNew(() =>
    {
        while (!fw.Done)
        {
            Console.SetCursorPosition(0, Console.CursorTop);
            Console.Write(string.Format("ContentLength: {0} | BytesWritten: {1}", fw.ContentLength, fw.BytesWritten));
        }
    });

    // Start the download...
    fw.Start();

    // Simulate pause...
    Thread.Sleep(500);
    fw.Pause();
    Thread.Sleep(2000);

    // Start the download from where we left, and when done print to console.
    fw.Start().ContinueWith(t => Console.WriteLine("Done"));

    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)