gpt4 book ai didi

c# - Console.ReadKey() 不工作

转载 作者:太空狗 更新时间:2023-10-29 23:21:41 29 4
gpt4 key购买 nike

请看original Microsoft example .

在第二个例子中我们发现如下代码:

// The simplest UI thread ever invented.
Task.Run(() =>
{
if (Console.ReadKey().KeyChar == 'c')
cts.Cancel();
});

(运行这个需要完整的代码:)

static int inputs = 2000;
static void Main(string[] args)
{
// The token source for issuing the cancelation request.
CancellationTokenSource cts = new CancellationTokenSource();

// A blocking collection that can hold no more than 100 items at a time.
BlockingCollection<int> numberCollection = new BlockingCollection<int>(100);

// Set console buffer to hold our prodigious output.
//Console.SetBufferSize(80, 2000);

// The simplest UI thread ever invented.
Task.Run(() =>
{
if (Console.ReadKey().KeyChar == 'c')
cts.Cancel();
else
{
Debugger.Break();
}
});

// Start one producer and one consumer.
Task.Run(() => NonBlockingConsumer(numberCollection, cts.Token));
Task.Run(() => NonBlockingProducer(numberCollection, cts.Token));

Console.WriteLine("Press the Enter key to exit.");
Console.ReadLine();
}

static void NonBlockingConsumer(BlockingCollection<int> bc, CancellationToken ct)
{
// IsCompleted == (IsAddingCompleted && Count == 0)
while (!bc.IsCompleted)
{
int nextItem = 0;
try
{
if (!bc.TryTake(out nextItem, 0, ct))
{
Console.WriteLine(" Take Blocked");
}
else
Console.WriteLine(" Take:{0}", nextItem);
}

catch (OperationCanceledException)
{
Console.WriteLine("Taking canceled.");
break;
}

// Slow down consumer just a little to cause
// collection to fill up faster, and lead to "AddBlocked"
Thread.SpinWait(500000);
}

Console.WriteLine("\r\nNo more items to take. Press the Enter key to exit.");
}

static void NonBlockingProducer(BlockingCollection<int> bc, CancellationToken ct)
{
int itemToAdd = 0;
bool success = false;

do
{
// Cancellation causes OCE. We know how to handle it.
try
{
// A shorter timeout causes more failures.
success = bc.TryAdd(itemToAdd, 2, ct);
}
catch (OperationCanceledException)
{
Console.WriteLine("Add loop canceled.");
// Let other threads know we're done in case
// they aren't monitoring the cancellation token.
bc.CompleteAdding();
break;
}

if (success)
{
Console.WriteLine(" Add:{0}", itemToAdd);
itemToAdd++;
}
else
{
Console.Write(" AddBlocked:{0} Count = {1}", itemToAdd.ToString(), bc.Count);
// Don't increment nextItem. Try again on next iteration.

//Do something else useful instead.
UpdateProgress(itemToAdd);
}

} while (itemToAdd < inputs);

// No lock required here because only one producer.
bc.CompleteAdding();
}

static void UpdateProgress(int i)
{
double percent = ((double)i / inputs) * 100;
Console.WriteLine("Percent complete: {0}", percent);
}

该代码应该做什么是完全清楚的:它应该在按 c 时中断,但它不起作用。相反,它会一直运行到结束,要求使用 Enter 关闭。

我们如何解决这个问题?

好像是线程的问题,不过是.net4.5的demo,代码不行。

'c' 的 KeyPress 没有设置 CancelationToken。

最佳答案

您在错误的例子上是完全正确的。它只是坏了。

它不起作用的原因是它不等待 Task 完成,而是等待 Console.ReadLine。这将修复它:

替换:

Task.Run(() => NonBlockingConsumer(numberCollection, cts.Token));
Task.Run(() => NonBlockingProducer(numberCollection, cts.Token));

与:

Task t1 = Task.Run(() => NonBlockingConsumer(numberCollection, cts.Token));
Task t2 = Task.Run(() => NonBlockingProducer(numberCollection, cts.Token));

Task.WaitAll(t1, t2);

关于c# - Console.ReadKey() 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31470247/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com