具有webrequests的多线程程序c#

时间:2014-09-26 13:01:08

标签: c# multithreading webrequest

我想制作多线程异步下载管理器。但我有多线程的问题。 一个线程正常工作,但是当我创建第二个线程时 - 什么都不起作用。 我假设webrequest同步的问题。我读了这个答案Multithreading a large number of web requests in c#,但我并不完全理解。现在提问:如何修改代码以使用多线程(Thread,Threadpool)。

班级DownloadableContent

{
    private string url { get; set; }
    private string path { get; set; }
    private Stream streamResponse { get; set; }
    private Stream streamLocal { get; set; }
    private HttpWebRequest webRequest { get; set; }
    private HttpWebResponse webResponse { get; set; }

    public DownloadableContent(string url, string path)
    {
        this.url = url;
        this.path = path;
    }

    public void Download()
    {
        using (WebClient wcDownload = new WebClient())
        {
            try
            {
                webRequest = (HttpWebRequest)WebRequest.Create(url);                 
                webRequest.Credentials = CredentialCache.DefaultCredentials;
                webResponse = (HttpWebResponse)webRequest.GetResponse();
                Int64 fileSize = webResponse.ContentLength;
                streamResponse = wcDownload.OpenRead(url);
                streamLocal = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
                byte[] downBuffer = new byte[2048];     
                int bytesSize = 0;
                while ((bytesSize = streamResponse.Read(downBuffer, 0, downBuffer.Length)) > 0)
                {
                    streamLocal.Write(downBuffer, 0, bytesSize);
                }
            }
            finally
            {
                streamResponse.Close();
                streamLocal.Close();
            }
        }
    }       
}

班级main

DownloadableContent file = new DownloadableContent("url", @"path");  
Thread thread = new Thread(file.Download);
thread.Start();

4 个答案:

答案 0 :(得分:1)

我能为您提供的最佳建议是使用TPL。它是Microsoft的一个很好的库,可以管理线程。我在我的代码中使用了这个类似的问题,基本上我必须下载8000个网址,在开始正常的过程需要30分钟。使用此库后,相同的过程在30秒内完成。

TPL LINK

Task Parallel Library (TPL)

请看一下示例:

BookStore- GitHub

答案 1 :(得分:0)

阅读异步编程是值得的 然后看看这个 http://msdn.microsoft.com/en-us/library/System.Net.WebClient_methods(v=vs.110).aspx 你有异步下载东西的方法。 另外看看TPL并避免线程 http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx

可能多读一点会帮助你避免很多麻烦。

这是一个简单的例子

private static void Main(string[] args)
{
    var urlsAndPaths = new Dictionary<string, string>();
    urlsAndPaths.Add("http://i.forbesimg.com/media/lists/people/lionel-messi_416x416.jpg","messi.jpg");
    urlsAndPaths.Add("http://sizzlingsuperstars.com/wp-content/uploads/2014/07/Cristiano-Ronaldo-2-480x309.jpg", "cristiano.jpg");            
    foreach (var kvp in urlsAndPaths)
    {
        var wc = new WebClient();
        wc.DownloadFileAsync(new Uri(kvp.Key),kvp.Value);
    }
    Console.ReadKey();
}

答案 2 :(得分:0)

根据您使用的.NET框架版本,您可以利用Task类。你可以做这样的事情

    foreach (var uri in myCollection)
    {
        Task.Factory.StartNew(() =>
        {
            try
            {
                using (System.Net.WebClient client = new System.Net.WebClient())
                {
                    client.DownloadFileCompleted += (o, args) =>
                    {
                        //Do something with the download
                    };
                    client.DownloadFileAsync(uri);

                }
            }
            catch (Exception ex)
            {
                //Do something
            }
        });
    }

答案 3 :(得分:0)

您使用的是.NET 4.5吗?执行此操作的“新方法”是Task.WhenAll,它使您的下载异步并行,但允许框架决定是否/何时应将工作安排到线程池。

var client = new System.Net.WebClient();
await Task.WhenAll(urls.Select(url => {
    var path = ?? // build local path based on url?
    return client.DownloadFileAsync(url, path);
});