2012-03-14 11 views
3

Monoを使用して、複数のファイルを同時にダウンロードできるプログラム(Mac OS XおよびDebian用)を開発しています。Mono on Mac OS X - パラレルHTTPダウンロードは2に制限

しかし、私はコンストラクタnew RollingDownload(10)を使用していますが、私は同時に2つのファイルをダウンロードすることができます。私が使用しているコードはこれです

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チャンネルの誰かが、問題を解決するために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