Подтвердить что ты не робот

Ограничивающие потоки пула потоков С#

Хорошо... Я дал сайту хороший поиск и прочитал много сообщений по этой теме. Я нашел этот вопрос: Код для простого пула потоков в С# особенно полезен.

Однако, как всегда кажется, мне нужно немного меняться.

Я просмотрел пример MSDN и немного адаптировал его ко мне. Пример, на который я ссылаюсь, приведен здесь: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx

Моя проблема в этом. У меня довольно простой набор кода, который загружает веб-страницу через классы HttpWebRequest и WebResponse и читает результаты через Stream. Я запускаю этот метод в потоке, поскольку его нужно будет выполнять много раз. Сам метод довольно короткий, но количество раз, которое его нужно уволить (с разными данными за каждый раз), меняется. Он может быть от 1 до 200.

Все, что я прочитал, похоже, указывает, что класс ThreadPool является основным кандидатом. Вот что становится сложнее. Мне может потребоваться, чтобы эта функция говорила 100 раз, но я могу иметь только 3 потока в большинстве случаев (для этой конкретной задачи).

Я попытался установить MaxThreads на ThreadPool с помощью:

ThreadPool.SetMaxThreads(3, 3);

Я не совсем уверен, что этот подход работает. Кроме того, я не хочу забивать другие веб-сайты или программы, запущенные в системе, и это будет продолжаться. Итак, ограничив # потоков на ThreadPool, могу ли я быть уверенным, что это относится только к моему коду и моим потокам?

В примере MSDN используется подход к событиям событий и вызывает WaitHandle.WaitAll(doneEvents);, как я это делаю.

Итак, в основе моего вопроса лежит вопрос о том, как обеспечить или указать максимальное количество потоков, которые могут быть запущены для их кода, но иметь код, который будет работать больше потоков, поскольку предыдущие заканчиваются до некоторой произвольной точки? Я решаю это правильно?

С уважением,

Джейсон


Хорошо, я добавил семафорный подход и полностью удалил код ThreadPool. Это кажется достаточно простым. Я получил информацию от: http://www.albahari.com/threading/part2.aspx

Этот пример показал мне, как:

[текст ниже здесь копия/вставка с сайта]

A Semaphore с емкостью одного похоже на a Mutex или lock, за исключением того, что Semaphore не имеет "владельца" - это нить-агностик. Любой поток может вызывать Release на Semaphore, а при Mutex и lock только поток, который получил ресурс, может его освободить.

В этом следующем примере десять потоков выполняют цикл с выражением Sleep в середине. A Semaphore гарантирует, что не более трех потоков может выполнить оператор 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();
        }
    }
}
4b9b3361

Ответ 1

Примечание. Если вы ограничиваете это на "3", чтобы не перегружать машину, запускающую ваше приложение, я бы сразу поставил перед собой задачу. Предполагается, что этот поток будет управлять этим для вас. С другой стороны, если вы не хотите перегружать какой-либо другой ресурс, читайте дальше!


Вы не можете управлять размером threadpool (или действительно что-нибудь о нем).

В этом случае я бы использовал семафор для управления доступом к вашему ресурсу. В вашем случае ваш ресурс запускает очистку веб-страниц или вычисляет отчет и т.д.

Чтобы сделать это, в своем статическом классе создайте объект семафора:

System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3);

Затем в каждом потоке вы делаете следующее:

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();
}

Каждый поток будет блокироваться на S.WaitOne(), пока не будет дан сигнал для продолжения. Как только S будет уменьшаться 3 раза, все потоки будут блокироваться, пока один из них не увеличит счетчик.

Это решение не идеально.


Если вы хотите что-то немного более чистым и более эффективным, я бы рекомендовал использовать метод BlockingQueue, в котором вы выполняете работу, которую хотите выполнить, в объект глобальной блокировки.

Между тем у вас есть три потока (которые вы создали, а не в threadpool), выходите из очереди, чтобы выполнить. Это не так сложно настроить и очень быстро и просто.

Примеры:

Ответ 2

Это статический класс, как любой другой, что означает, что все, что вы делаете с ним, влияет на любой другой поток текущего процесса. Это не влияет на другие процессы.

Однако я считаю, что это один из больших недостатков дизайна в .NET. Кто придумал блестящую идею сделать пул потоков статичным? Как показывает ваш пример, мы часто хотим, чтобы пул потоков, посвященный нашей задаче, не вмешивался в несвязанные задачи в другом месте системы.