2012-03-14 32 views
3

我使用Mono開發可同時下載多個文件的程序(適用於Mac OS X和Debian)。Mac OS X上的Mono - 並行HTTP下載限制爲2

但是我只能夠同時下載2個文件,雖然我使用構造函數new RollingDownload(10)。我正在使用的代碼是這樣的

using System; 
using System.Collections.Generic; 
using System.Collections.Concurrent; 
using System.Threading; 
using System.Net; 
using System.Diagnostics; 
using System.IO; 
namespace worker 
{ 
    public class RollingDownload 
    { 
     private static ConcurrentQueue<Download> _downloads = new ConcurrentQueue<Download>(); 
     private static short _NumberOfThreads; 
     private static short DefaultTimeoutSeconds = 20; 
     public RollingDownload (short NumberOfThreads) 
     { 
      _NumberOfThreads = NumberOfThreads; 
     } 

     public void addDownload(Download download) { 
      _downloads.Enqueue(download); 
     } 
     public void SpawnWebRequests() 
     { 
      ServicePointManager.DefaultConnectionLimit = _NumberOfThreads; 
      ServicePointManager.MaxServicePoints = _NumberOfThreads; 
      IList<Thread> threadList = new List<Thread>(); 

      for (int i = 0; i < _NumberOfThreads; i++) 
      { 
       var thread = new Thread(ProcessWebRequests); 
       threadList.Add(thread); 
       thread.Start(); 
      } 

      for (int i = 0; i < _NumberOfThreads; i++) 
      { 
       threadList[i].Join(); 
      } 
     } 

     private static void ProcessWebRequests() 
     { 
      while (true) 
      { 
       Download download; 
       Console.WriteLine (Thread.CurrentThread.ManagedThreadId); 
       if(_downloads.TryDequeue(out download)) { 
        ProcessWebRequest(download); 
       } else { 
        break; 
       } 
      } 
     } 

     private static void ProcessWebRequest(Download download) 
     { 
      try 
      { 
       var request = (HttpWebRequest)WebRequest.Create(download.Url); 
       request.Method = "GET"; // or "GET", since some sites (Amazon) don't allow HEAD 
       request.Timeout = DefaultTimeoutSeconds * 1000; 
       request.AllowAutoRedirect = true; 
       //request.ServicePoint.ConnectionLimit = _NumberOfThreads; 
       request.KeepAlive = false; 
       //request.ServicePoint = ServicePointManager.FindServicePoint(new Uri(download.Url)); 
       // Get the response (throws an exception if status != 200) 
       using (var response = (HttpWebResponse)request.GetResponse()) 
       { 
        if (response.StatusCode == HttpStatusCode.OK) { 
         /*string contents = ""; 
         using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
         { 
          contents = reader.ReadToEnd(); 
         }*/ 
         download.onCompleted(response.GetResponseStream(), response.StatusCode); 
        } 
       } 
      } 
      catch (WebException ex) 
      { 
       var response = ((HttpWebResponse)ex.Response); 
       var status = response != null 
           ? response.StatusCode 
           : HttpStatusCode.RequestTimeout; 

       Console.WriteLine(String.Format("Broken link ({0}): {1}", status, download.Url), ex); 

       // Don't rethrow, as this is an expected exception in many cases 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(String.Format("Error processing link {0}", download.Url), ex); 

       // Rethrow, something went wrong 
       throw; 
      } 
     } 
    } 
public class Download 
    { 
     public string Url { get; set; } 

     public string PathToSave { get; set; } 

     public Download (String Url) 
     { 
      this.Url = Url; 
     } 

     public void onCompleted (Stream response, HttpStatusCode httpcode) 
     { 
      Console.WriteLine ("hello everybody: " + httpcode.ToString()); 
     } 
    } 
} 

嗯,我不知道。 #mono IRC Channel中的某個人意味着,我應該使用this ticket來解決問題,但我不知道在哪裏可以找到machine.config或如何在monodevelop中添加它。

我正在開發的應用程序是一個使用C#的控制檯應用程序(無ASP!)。

很高興收到你們的來信。

回答

3

是從同一主機下載的嗎?如果是這樣,你需要添加一些代碼的RollingDownload構造(或其他初始化代碼):

string downloadHost = ...; 
ServicePoint sp = ServicePointManager.FindServicePoint(new Uri(downloadHost)); 
sp.ConnectionLimit = _NumberOfThreads; 

[感謝this blog,幫助我類似的問題早]

+0

的感謝!那就是訣竅:-)) – Stefan 2012-03-15 09:10:05