如何通过按键中断程序
How to interrupt a program by a key press
我想通过按 T 键来中断我的生产者-消费者程序。我搜索了很多答案,但我无法弄清楚为什么 它不起作用。
static void Main(string[] args)
{
Buffer buffer = new Buffer();
Produtor prod = new Produtor(buffer);
Thread threadProdutor = prod.CriarThreadProdutor();
Consumidor cons = new Consumidor(buffer, 100000);
Thread threadConsumidor = cons.CriarThreadConsumidor();
threadProdutor.Start();
threadConsumidor.Start();
threadProdutor.Join();
threadConsumidor.Join();
while (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.T)
{
Environment.Exit(0);
}
}
我在 while 中添加了断点,但程序甚至无法到达那里。
通过将循环放在 Join()
调用之后,线程将在您检查控制台输入时已经完成,因此您需要颠倒顺序。
此外,while
循环只会进入并继续 运行 如果有可用的密钥并且它是 T
。您想要相反的方法:循环 直到 一个密钥可用并且它是 T
.
最后,Console.ReadKey()
会阻塞,直到按下一个键,所以你也不需要检查 Console.KeyAvailable
,除非你想在等待 [=15= 时做其他事情](例如显示进度或检查线程是否自行完成)。
while (Console.ReadKey(true).Key != ConsoleKey.T)
{
// Do nothing...
}
// T has been pressed
// Signal to the threads to stop
// Set a flag, Cancel() a CancellationTokenSource, etc.
// Wait for the threads to terminate
threadProdutor.Join();
threadConsumidor.Join();
// Exit the program
Environment.Exit(0);
要在等待中断键时显示进度,可以这样重写循环...
TimeSpan progressInterval = TimeSpan.FromSeconds(1);
// complete is a simple flag set by the consumer(s)
// Only call ReadKey() when KeyAvailable so it can't block longer than updateInterval
while (!complete && (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.T))
{
Console.WriteLine($"Current time is {DateTime.Now:HH:mm:ss.fff}");
Thread.Sleep(progressInterval);
}
请注意,这具有在整个 progressInterval
期间始终处于休眠状态的缺点,即使在此之前已经满足退出条件。一个简单的解决方法是将检查之间的时间减少到 1 / n
,然后仅在每次 n
th 检查后显示进度...
TimeSpan progressInterval = TimeSpan.FromSeconds(1);
const int ReadsPerProgressInterval = 10;
TimeSpan sleepTimeout = new TimeSpan(progressInterval.Ticks / ReadsPerProgressInterval);
int readCount = 0;
// complete is a simple flag set by the consumer(s)
// Only call ReadKey() when KeyAvailable so it can't block longer than updateInterval
while (!complete && (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.T))
{
// This won't display progress until after progressInterval has elapsed
// To display initial progress:
// A) change to == 1, or...
// B) duplicate progress display to before the loop as well
if (++readCount % ReadsPerProgressInterval == 0)
Console.WriteLine($"Current time is {DateTime.Now:HH:mm:ss.fff}");
Thread.Sleep(sleepTimeout);
}
我想通过按 T 键来中断我的生产者-消费者程序。我搜索了很多答案,但我无法弄清楚为什么 它不起作用。
static void Main(string[] args)
{
Buffer buffer = new Buffer();
Produtor prod = new Produtor(buffer);
Thread threadProdutor = prod.CriarThreadProdutor();
Consumidor cons = new Consumidor(buffer, 100000);
Thread threadConsumidor = cons.CriarThreadConsumidor();
threadProdutor.Start();
threadConsumidor.Start();
threadProdutor.Join();
threadConsumidor.Join();
while (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.T)
{
Environment.Exit(0);
}
}
我在 while 中添加了断点,但程序甚至无法到达那里。
通过将循环放在 Join()
调用之后,线程将在您检查控制台输入时已经完成,因此您需要颠倒顺序。
此外,while
循环只会进入并继续 运行 如果有可用的密钥并且它是 T
。您想要相反的方法:循环 直到 一个密钥可用并且它是 T
.
最后,Console.ReadKey()
会阻塞,直到按下一个键,所以你也不需要检查 Console.KeyAvailable
,除非你想在等待 [=15= 时做其他事情](例如显示进度或检查线程是否自行完成)。
while (Console.ReadKey(true).Key != ConsoleKey.T)
{
// Do nothing...
}
// T has been pressed
// Signal to the threads to stop
// Set a flag, Cancel() a CancellationTokenSource, etc.
// Wait for the threads to terminate
threadProdutor.Join();
threadConsumidor.Join();
// Exit the program
Environment.Exit(0);
要在等待中断键时显示进度,可以这样重写循环...
TimeSpan progressInterval = TimeSpan.FromSeconds(1);
// complete is a simple flag set by the consumer(s)
// Only call ReadKey() when KeyAvailable so it can't block longer than updateInterval
while (!complete && (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.T))
{
Console.WriteLine($"Current time is {DateTime.Now:HH:mm:ss.fff}");
Thread.Sleep(progressInterval);
}
请注意,这具有在整个 progressInterval
期间始终处于休眠状态的缺点,即使在此之前已经满足退出条件。一个简单的解决方法是将检查之间的时间减少到 1 / n
,然后仅在每次 n
th 检查后显示进度...
TimeSpan progressInterval = TimeSpan.FromSeconds(1);
const int ReadsPerProgressInterval = 10;
TimeSpan sleepTimeout = new TimeSpan(progressInterval.Ticks / ReadsPerProgressInterval);
int readCount = 0;
// complete is a simple flag set by the consumer(s)
// Only call ReadKey() when KeyAvailable so it can't block longer than updateInterval
while (!complete && (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.T))
{
// This won't display progress until after progressInterval has elapsed
// To display initial progress:
// A) change to == 1, or...
// B) duplicate progress display to before the loop as well
if (++readCount % ReadsPerProgressInterval == 0)
Console.WriteLine($"Current time is {DateTime.Now:HH:mm:ss.fff}");
Thread.Sleep(sleepTimeout);
}