2014-09-26 81 views
0

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

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(); 
+0

你的代码很混乱。你正在使用'WebClient' *和*'HttpWebRequest'。因此,您正在为每个网址提出两个请求。您应该删除'webRequest'和'webResponse',并使用'WebClient'。 – 2014-09-26 16:23:28

+0

很可能你遇到问题的原因是你没有处理你正在创建的'webRequest'和'webResponse'对象。我从经验中知道,这往往会导致事情在几个请求后停止工作。由于您没有使用它们,只需将它们从代码中移除即可。 – 2014-09-26 16:25:09

+0

我只在代码中留下了'Webclient',现在效果很好 – 2014-09-27 15:37:28

回答

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(); 
} 
+0

感谢您的回答,看起来不错,但是程序条件是“New Thread in New Thread”(训练任务)使用Thread和Threadpool。 (两个不同的实现) – 2014-09-26 13:24:49

+0

我认为有人需要更新他们的培训材料:) – 2014-09-26 14:22:19

+0

这是新手的任务。NET :) – 2014-09-27 15:35:07

0

根据您所使用的.NET framework版本,你可以利用任务类的。你可以这样做

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 
      } 
     }); 
    } 
1

我可以给你的最好的建议是使用TPL。这是一个从微软到管理线程的好库。在我的代码中,我曾使用过这个类似的问题,基本上我必须下载8000个URL,开始时正常过程需要30分钟。使用这个库后,同样的过程在30秒内完成。

TPL LINK

Task Parallel Library (TPL)

请,拿在例子看看:

BookStore- GitHub

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); 
}); 
+0

thx为答案,但我使用.NET 4.0 – 2014-09-26 14:00:28