2014-09-26 114 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