C# 如何通过按键中断程序

C# 如何通过按键中断程序,c#,multithreading,monitor,C#,Multithreading,Monitor,我想按T键来中断我的制作人-消费者程序。我搜索了很多答案,但我不明白为什么它不起作用 static void Main(字符串[]args) { 缓冲区=新缓冲区(); Produtor prod=新Produtor(缓冲区); Thread threadProdutor=产品CriarThreadProdutor(); Consumidor cons=新Consumidor(缓冲区,100000); Thread threadConsumidor=cons.CriarThreadConsumi

我想按T键来中断我的制作人-消费者程序。我搜索了很多答案,但我不明白为什么它不起作用

static void Main(字符串[]args)
{
缓冲区=新缓冲区();
Produtor prod=新Produtor(缓冲区);
Thread threadProdutor=产品CriarThreadProdutor();
Consumidor cons=新Consumidor(缓冲区,100000);
Thread threadConsumidor=cons.CriarThreadConsumidor();
threadProdutor.Start();
threadConsumidor.Start();
threadProdutor.Join();
threadConsumidor.Join();
while(Console.KeyAvailable&&Console.ReadKey(true.Key==ConsoleKey.T)
{
环境。退出(0);
}
}

我在while中添加了一个断点,但程序甚至无法到达那里。

将循环放在您的
Join()
调用之后,当您检查控制台的输入时,线程将已经完成,因此您需要颠倒顺序

此外,只有在有可用钥匙且钥匙为
T
时,才会进入
while
循环并继续运行。您想要的是相反的:循环直到一个键可用并且它是
T

最后,
Console.ReadKey()
阻塞直到按下一个键,因此您也不需要检查
Console.KeyAvailable
,除非您在等待
t
时想做其他事情(例如显示进度或检查线程是否自行完成)

while(Console.ReadKey(true.Key!=ConsoleKey.T)
{
//什么也不做。。。
}
//T已按下
//向线程发出停止的信号
//设置标志、Cancel()和CancellationTokenSource等。
//等待线程终止
threadProdutor.Join();
threadConsumidor.Join();
//退出程序
环境。退出(0);
要在等待中断键时显示进度,可以像这样重写循环

TimeSpan progressInterval=TimeSpan.FromSeconds(1);
//complete是消费者设置的简单标志
//仅在KeyAvailable时调用ReadKey(),这样它的阻止时间就不会超过updateInterval
而(!complete&&(!Console.KeyAvailable | | Console.ReadKey(true.Key!=ConsoleKey.T))
{
WriteLine($“当前时间为{DateTime.Now:HH:mm:ss.fff}”);
线程。睡眠(进程间隔);
}
请注意,这样做的缺点是在整个
progressInterval
期间始终处于睡眠状态,即使在此之前已满足退出条件。一个简单的解决方法是将两次检查之间的时间缩短到
1/n
,然后仅在每次
n
第次检查后显示进度

TimeSpan progressInterval=TimeSpan.FromSeconds(1);
常量int ReadsPerProgressInterval=10;
TimeSpan sleepTimeout=新的TimeSpan(progressInterval.Ticks/ReadsPerProgressInterval);
int readCount=0;
//complete是消费者设置的简单标志
//仅在KeyAvailable时调用ReadKey(),这样它的阻止时间就不会超过updateInterval
而(!complete&&(!Console.KeyAvailable | | Console.ReadKey(true.Key!=ConsoleKey.T))
{
//直到progressInterval结束后,才会显示进度
//要显示初始进度,请执行以下操作:
//A)更改为==1,或。。。
//B)将进度显示复制到循环之前
如果(++readCount%ReadsPerProgressInterval==0)
WriteLine($“当前时间为{DateTime.Now:HH:mm:ss.fff}”);
睡眠(睡眠超时);
}

我确实在使用Console.WriteLine()添加显示进度,那么,我需要使用KeyAvailable吗?是的,在这种情况下,您需要检查
KeyAvailable
以确保
ReadKey()
不会阻塞太长时间。我已经更新了我的答案,以说明如何做到这一点。