Задача, что 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.");
});
}
}