Задача, что ReadsKey с клавиатуры не работает - шаблон Consumer/Producer

Я реализую один шаблон производителя / потребителя с использованием BlockingCollection.

Когда я нажимаю "c" на клавиатуре, я хочу отменить операцию, используя CancellationToken.

Странно то, что если я нажму "c" так быстро, как смогу после запуска программы, программа прослушает событие.

Если я нажму "c" позже, скажем, на 45000-й итерации программа не реагирует.

У меня есть цикл, который заполняет производителя.

        for (int i = 0; i < 50000; i++)
        {
            logger.AddToQueue("Number with flush " + i, true);
        }
        logger.DataItems.CompleteAdding();

В конструкторе logger я вызываю этот метод:

    private Task t;
    public void KeyPress()
    {

       t = Task.Run(() =>
            {
                if (Console.ReadKey(true).KeyChar == 'c')
                {
                        cts.Cancel();
                }
            });
    }

Я не знаю, относится ли ошибка к другим методам, но я опубликую их на всякий случай:

AddToQueue (Производитель):

    public void AddToQueue(String text, bool isFlushOn) {
         Consumer(isFlushOn);
            try {
                 _dataItems.TryAdd(new LogLine() { Text = text, Timestamp = DateTime.Now }, 0, ct);
            } catch (OperationCanceledException) {
                _dataItems.CompleteAdding();
            }
    }

и потребитель:

    Task task = null;
    public void Consumer(bool isStopWithFlushOn)
    {

        if (task == null)
        {
            task = Task.Run(() =>
            {
                while (!_dataItems.IsCompleted) {
                    try {
                        LogLine data = null;
                        if (!_dataItems.TryTake(out data, 5, ct)) {
                            Console.WriteLine(" Take Blocked");
                        } else {
                            StringBuilder stringBuilder = new StringBuilder();
                            stringBuilder.Append(data.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                            stringBuilder.Append("\t");
                            stringBuilder.Append(data.LineText());
                            stringBuilder.Append("\t");
                            _writer.WriteLine(stringBuilder.ToString());
                            Console.WriteLine(" Take:{0}", data.Text);
                        }
                    } catch (OperationCanceledException) {
                        if (isStopWithFlushOn) {
                            Console.WriteLine("Canceled with flush.");
                            foreach (var dataItem in _dataItems.GetConsumingEnumerable()) {
                                Console.WriteLine("Canceled Take:{0}", dataItem.Text);
                                StringBuilder stringBuilder = new StringBuilder();

                                stringBuilder.Append(dataItem.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                                stringBuilder.Append("\t");
                                stringBuilder.Append("Number with flush " + dataItem.LineText());
                                stringBuilder.Append("\t");
                                _writer.WriteLine(stringBuilder.ToString());
                                Thread.SpinWait(500000);
                            }
                        } else {
                            Console.WriteLine("Canceled without flush.");
                            break;
                        }
                    }

                }
                Console.WriteLine("\r\nNo more items to take.");
            });
        }
    }

0 ответов

Другие вопросы по тегам