ThreadPool - Предел обработки WaitAll 64

Я пытаюсь обойти ограничение дескриптора wait64, которое накладывает .net 3.5

Я видел эту тему: Обходной путь для ограничения дескриптора WaitHandle.WaitAll 64?

Итак, я понимаю общую идею, но у меня возникают трудности, потому что я не использую делегата, а, скорее,

Я в основном работаю над этим примером: http://msdn.microsoft.com/en-us/library/3dasc8as%28VS.80%29.aspx

Эта ссылка http://www.switchonthecode.com/tutorials/csharp-tutorial-using-the-threadpool аналогичен, но снова переменная int, отслеживающая задачи, является переменной-членом.

Куда в приведенном выше примере передать целое число threadCount? Могу ли я передать его в методе обратного вызова как объект? Я думаю, у меня проблемы с методом обратного вызова и передачей по ссылке.

Спасибо Стивен,

Мне эта ссылка не совсем понятна.

Разрешите опубликовать свой код, чтобы помочь себе уточнить:

for (int flows = 0; flows < NumFlows; flows++)
{
ResetEvents[flows] = new ManualResetEvent(false);
ICalculator calculator = new NewtonRaphson(Perturbations);
Calculators[flows] = calculator;
ThreadPool.QueueUserWorkItem(calculator.ThreadPoolCallback, flows);
}
resetEvent.WaitOne();

Куда бы я передал свою переменную threadCount. Я предполагаю, что его нужно уменьшить в калькуляторе.


person bearrito    schedule 30.06.2010    source источник
comment
Извините, я полагаю, что имел в виду threadCount из первой ссылки.   -  person bearrito    schedule 30.06.2010
comment
Незначительный технический момент: ограничение в 64 дескриптора налагается Win32 API, а не .NET 3.5. Итак, каждая программа в Windows имеет одно и то же ограничение.   -  person Stephen Cleary    schedule 30.06.2010


Ответы (2)


Не следует использовать несколько дескрипторов ожидания, чтобы дождаться завершения нескольких рабочих элементов в ThreadPool. Мало того, что он не масштабируется, вы в конечном итоге столкнетесь с ограничением в 64 дескриптора, наложенным методом WaitHandle.WaitAll (как вы уже сделали). Правильный шаблон для использования в этой ситуации - это дескриптор ожидания подсчета. Один из них доступен для загрузки Reactive Extensions для .NET 3.5 через Класс CountdownEvent.

var finished = new CountdownEvent(1);
for (int flows = 0; flows < NumFlows; flows++) 
{ 
  finished.AddCount();
  ICalculator calculator = new NewtonRaphson(Perturbations); 
  Calculators[flows] = calculator; 
  ThreadPool.QueueUserWorkItem(
    (state) =>
    {
      try 
      { 
        calculator.ThreadPoolCallback(state); 
      }
      finally 
      { 
        finished.Signal(); 
      }
    }, flows);
} 
finished.Signal();
finished.Wait();
person Brian Gideon    schedule 01.10.2010

Анонимный метод может быть самым простым:

int threadCount = 0;
for (int flows = 0; flows < NumFlows; flows++)
{
    ICalculator calculator = new NewtonRaphson(Perturbations);
    Calculators[flows] = calculator;

    // We're about to queue a new piece of work:
    //    make a note of the fact a new work item is starting
    Interlocked.Increment(ref threadCount);
    ThreadPool.QueueUserWorkItem(
        delegate
        {
            calculator.ThreadPoolCallback(flows);

            // We've finished this piece of work...
            if (Interlocked.Decrement(ref threadCount) == 0)
            {
                // ...and we're the last one.
                // Signal back to the main thread.
                resetEvent.Set();
            }
        }, null);
}
resetEvent.WaitOne();
person Tim Robinson    schedule 30.06.2010
comment
Если вы посмотрите на предоставленные ссылки, вы увидите, что я стараюсь избегать использования анонимных методов. - person bearrito; 02.07.2010
comment
Я не понимаю, почему вы избегаете анонимных методов - вы ориентируетесь на среду выполнения .NET 1.0 или 1.1? - person Tim Robinson; 02.07.2010
comment
Здесь есть очень тонкая ошибка. WaitOne и Interlocked.Decrement будут гоняться, что приведет к слишком раннему возврату WaitOne, если последний рабочий элемент был поставлен в очередь и завершился до того, как следующая итерация цикла получит шанс Interlocked.Increment. - person Brian Gideon; 01.10.2010
comment
Однако решение действительно простое. Относитесь к потоку очереди как к рабочему элементу. Увеличивайте threadCount перед циклом и уменьшайте после цикла и сигнализируйте точно так же, как и рабочие элементы. - person Brian Gideon; 01.10.2010