Mono на Mac OS X - количество параллельных загрузок HTTP ограничено 2 - PullRequest
3 голосов
/ 14 марта 2012

Я использую Mono для разработки программы (для Mac OS X и Debian), которая может одновременно загружать несколько файлов.

Однако я могу загрузить только 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 ());
        }
    }
}

Ну, я не знаю. Кто-то на IRC-канале #mono имел в виду, что я должен использовать этот билет для решения проблем, но я не знаю, где найти machine.config или как добавить его в monodevelop.

Приложение, которое я разрабатываю, - это консольное приложение (без ASP!), Использующее C #.

Было бы здорово услышать от вас, ребята.

1 Ответ

3 голосов
/ 15 марта 2012

Ваши загрузки с одного хоста?Если это так, вам нужно добавить некоторый код в конструктор RollingDownload (или другой код инициализации):

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

[Кредит этому блогу , который помог мнеаналогичная проблема ранее.]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...