2012-03-14 2 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