У меня есть простая настройка потребителя производителя с использованием коллекции блокировок. Потребитель сидит в цикле на протяжении нашего приложения, ожидая, пока потребитель поместит элементы в коллекцию, затем извлекает элемент и записывает его в последовательный порт. По какой-то причине collection.Take () блокируется навсегда, когда в коллекции есть элементы. Для этого приложения у нас может быть один или несколько таких активных производителей одновременно. Они ведут себя одинаково независимо.
public class ProducerConsumer
{
private Task _backgroundWorker;
private CancellationTokenSource _cancellationTokenSource;
private BlockingCollection<Data> _dataQueue;
public ProducerConsumer()
{
_dataQueue = new BlockingCollection<Data>();
_cancellationTokenSource = new CancellationTokenSource();
_backgroundWorker = new Task(() => DoWork(_cancellationTokenSource.Token), TaskCreationOptions.LongRunning);
_backgroundWorker.Start();
}
public void AddData(Data data)
{
_dataQueue.Add(data);
System.Diagnostics.Debug.WriteLine(_dataQueue.Count);
}
private void DoWork(CancellationToken cancellationToken)
{
while(!cancellationToken.IsCancellationRequested)
{
try
{
_dataQueue.Take(cancellationToken); //This is blocking forever
//DoWork
}
catch(OperationCanceledException) { }
catch(Exception e)
{
System.Diagnostics.Debug.WriteLine(e.ToString());
throw;
}
}
}
}
При выполнении этого оператора печати увеличивается, поэтому у нас определенно есть данные в коллекции, но по какой-либо причине Take () продолжает блокировать.
Это также не исключение.
Отмена запрашивается с помощью Dispose (), но я не добавил это здесь. Это не называется называться рано.
Я пытался использовать .GetConsumingEnumerable (), и это также навсегда блокирует.
Я неправильно запускаю задание? Могу ли я исчерпать темы?
Я рассмотрел использование BackgroundWorker вместо Задачи, но согласно MSFT Задача предпочтительнее.
Заранее спасибо.