3

Я играл с BlockingCollection, чтобы попытаться лучше понять их, но я изо всех сил, чтобы понять, почему мой код зависает, когда он завершит обработку всех моих вещей, когда я использую Parallel.ForBlockingCollection с Parallel.For зависает?

Я просто добавить номер для него (производителя):

var blockingCollection = new BlockingCollection<long>(); 

Task.Factory.StartNew(() => 
{ 
    while (count <= 10000) 
    { 
     blockingCollection.Add(count); 
     count++; 
    } 
}); 

Тогда я пытаюсь обработать (Consumer):

Parallel.For(0, 5, x => 
{ 
    foreach (long value in blockingCollection.GetConsumingEnumerable()) 
    { 
     total[x] += 1; 
     Console.WriteLine("Worker {0}: {1}", x, value); 
    } 
}); 

Но когда он завершает обработку всех номеров, он просто висит там? Что я делаю не так?

Также, когда я устанавливаю свой Parallel.For до 5, означает ли это, что он обрабатывает данные на 5 отдельных потоков?

+0

[Вы должны задать только один вопрос на вопрос.] (Http: //meta.stackexchange.com/q/39223/130186) – svick

ответ

2

Как следует из его названия, операции над блоком BlockingCollection<T> блокируются, когда они ничего не могут сделать, и это включает в себя GetConsumingEnumerable().

Причина в том, что коллекция не может определить, был ли ваш продюсер уже выполнен или просто занят производством следующего элемента.

Что вам нужно сделать, это уведомить коллекцию, что вы сделали, добавляя к ней предметы, позвонив по телефону CompleteAdding(). Например:

while (count <= 10000) 
{ 
    blockingCollection.Add(count); 
    count++; 
} 

blockingCollection.CompleteAdding(); 
3

Это GetConsumingEnumerable метод особенность.

Перечисление коллекции таким образом блокирует потребительский поток, если элементы не доступны или коллекция пуста.

Вы можете прочитать больше об этом here

Также использование Parallel.For(0,5) не гарантирует, что данные будут обрабатываться в 5 отдельных нитей. Это зависит от Environment.ProcessorCount.

1

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

Нет, цитата из предыдущего ответа на SO (How many threads Parallel.For(Foreach) will create? Default MaxDegreeOfParallelism?):

по умолчанию планировщик для Task Parallel Library и PLINQ использует .NET Framework ThreadPool в очередь и выполнять работу. В .NETFramework 4 ThreadPool использует информацию, предоставляемую типом System.Threading.Tasks.Task, чтобы эффективно поддерживать мелкозернистый параллелизм (краткосрочные единицы работы) задач и запросов часто представляют.

Проще говоря, TPL создает Задачи, а не потоки. Структура решает, сколько потоков должно обрабатывать их.

+1

Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [Из обзора] (/ review/low-quality-posts/11400952) –

+0

@ RenéVogt Я не думал об этом, спасибо :) –

Смежные вопросы