Ограничивающие streamи пула streamов C #
Хорошо … Я дал сайту честный поиск и прочитал много сообщений по этой теме. Я нашел этот вопрос: особенно полезен код для простого пула streamов в C # .
Однако, как всегда кажется, мне нужно немного меняться.
Я просмотрел пример MSDN и немного адаптировал его ко мне. Пример, на который я ссылаюсь, приведен здесь: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx
- Объединение streamов в C ++ 11
- Тема против ThreadPool
- Как я могу отключить пулы исполнителей / планировщиков Spring Spring до того, как все остальные бобы в веб-приложении будут уничтожены?
- Что такое эквивалент async / await сервера ThreadPool?
- Когда использовать пул streamов в C #?
Моя проблема в этом. У меня довольно простой набор кода, который загружает веб-страницу через HttpWebRequest
и WebResponse
и считывает результаты через Stream
. Я запускаю этот метод в streamе, поскольку его нужно будет выполнять много раз. Сам метод довольно короткий, но количество раз, которое его нужно уволить (с разными данными за каждый раз), меняется. Он может быть от 1 до 200.
Все, что я читал, похоже, указывает, что class ThreadPool
является главным кандидатом. Вот что становится сложнее. Мне может потребоваться, чтобы эта функция говорила 100 раз, но я могу иметь только 3 streamа в большинстве случаев (для этой конкретной задачи).
Я попытался установить MaxThreads
на ThreadPool
через:
ThreadPool.SetMaxThreads(3, 3);
Я не совсем уверен, что этот подход работает. Кроме того, я не хочу забивать другие веб-сайты или программы, запущенные в системе, и это будет продолжаться. Итак, ограничив число streamов ThreadPool
, могу ли я быть уверенным, что это относится только к моему коду и моим streamам?
В примере MSDN используется подход к управлению событиями и вызывает WaitHandle.WaitAll(doneEvents);
как я это делаю.
Итак, в основе моего вопроса лежит вопрос о том, как обеспечить или указать максимальное количество streamов, которые могут быть запущены для их кода, но иметь код, который будет работать больше streamов, поскольку предыдущие заканчиваются до некоторой произвольной точки? Правильно ли я занимаюсь этим?
С уважением,
Джейсон
Хорошо, я добавил семафорный подход и полностью удалил код ThreadPool
. Это кажется достаточно простым. Я получил информацию от: http://www.albahari.com/threading/part2.aspx
Именно этот пример показал мне, как:
[текст ниже здесь копия / вставка с сайта]
Semaphore
с емкостью одного похож на Mutex
или lock
, за исключением того, что у Semaphore
нет «владельца» – это нить-агностик. Любой stream может вызвать Release
на Semaphore
, а при Mutex
и lock
только stream, который получил ресурс, может его освободить.
В следующем примере десять streamов выполняют цикл с инструкцией Sleep
в середине. Semaphore
гарантирует, что не более трех streamов может выполнить этот оператор Sleep
сразу:
class SemaphoreTest { static Semaphore s = new Semaphore(3, 3); // Available=3; Capacity=3 static void Main() { for (int i = 0; i < 10; i++) new Thread(Go).Start(); } static void Go() { while (true) { s.WaitOne(); Thread.Sleep(100); // Only 3 threads can get here at once s.Release(); } } }
- WaitAll для нескольких дескрипторов в streamе STA не поддерживается
- Как реализовать PriorityBlockingQueue с помощью ThreadPoolExecutor и настраиваемых задач
- C # - ThreadPool vs Tasks
- Сколько streamов слишком много?
- Пул streamов C ++
- Как создать пул streamов, используя boost в C ++?
- Именование streamов и streamов-streamов ExecutorService
- Код для простого пула streamов в C #
Примечание. Если вы ограничиваете это на «3», чтобы не перегружать машину, на которой работает ваше приложение, я бы сразу подумал, что это проблема. Предполагается, что этот stream будет управлять этим для вас. С другой стороны, если вы не хотите перегружать какой-либо другой ресурс, тогда читайте дальше!
Вы не можете управлять размером threadpool (или действительно что-нибудь о нем).
В этом случае я бы использовал семафор для управления доступом к вашему ресурсу. В вашем случае ваш ресурс запускает веб-очистку или вычисляет отчет и т. Д.
Чтобы сделать это, в своем статическом classе создайте объект семафора:
System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3);
Затем в каждом streamе вы делаете следующее:
System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3); try { // wait your turn (decrement) S.WaitOne(); // do your thing } finally { // release so others can go (increment) S.Release(); }
Каждый stream будет блокироваться на S.WaitOne (), пока не будет дан сигнал для продолжения. После того, как S будет уменьшаться 3 раза, все streamи будут блокироваться, пока один из них не увеличит счетчик.
Это решение не идеально.
Если вы хотите что-то немного более чистым и более эффективным, я бы рекомендовал использовать метод BlockingQueue, в котором вы выполняете работу, которую хотите выполнить, в глобальном объекте Blocking Queue.
Между тем у вас есть три streamа (которые вы создали, а не в threadpool), и выходите из очереди для выполнения. Это не так сложно настроить и очень быстро и просто.
Примеры:
- Лучший пример очереди / наилучшая практика
- Лучший способ получить объекты из BlockingQueue в параллельной программе?
Это статический class, как любой другой, что означает, что все, что вы делаете с ним, влияет на любой другой stream текущего процесса. Это не влияет на другие процессы.
Однако я считаю, что это один из больших недостатков дизайна в .NET. Кто придумал блестящую идею сделать пул streamов статичным ? Как показывает ваш пример, мы часто хотим, чтобы пул streamов, посвященный нашей задаче, не мешал несвязанным задачам в другом месте в системе.