在控制台窗口应用程序中通过用户输入暂停当前线程
这是我想出的用于暂停/恢复控制台内活动线程的解决方案......
它需要第二个线程进行输入,主循环也会做出反应。但我对C#的无知让我想知道是否有更简单的解决方案?也许可以单独使用主线程来完成?
本质上,我正在测试将以定义的 FPS 迭代的几项内容,并且我希望能够通过键盘输入暂停和恢复迭代。如有任何反馈,我们将不胜感激。
class TestLoops
{
int targetMainFPS = 5;
int targetInputFPS = 3;
bool CONTINUE = true;
Thread testLoop, testLoop2;
ConsoleKeyInfo cki;
ManualResetEvent resetThread = new ManualResetEvent(true); //How to correctly pause threads in C#.
public void Resume() { resetThread.Set(); }
public void Pause() { resetThread.Reset(); }
public TestLoops()
{
//_start = DateTime.Now.Ticks;
Console.Write("CreatingLoop...");
this.testLoop = new Thread(MainLoop);
this.testLoop.Start();
this.testLoop2 = new Thread(InputLoop);
this.testLoop2.Start();
}
void MainLoop()
{
long _current = 0;
long _last = 0;
Console.Write("MainLoopStarted ");
while(CONTINUE)
{
resetThread.WaitOne();
_current = DateTime.Now.Ticks / 1000;
if(_current > _last + (1000 / targetMainFPS) )
{
_last = _current;
//Do something...
Console.Write(".");
}
else
{
System.Threading.Thread.Sleep(10);
}
}
}
void InputLoop()
{
long _current = 0;
long _last = 0;
Console.Write("InputLoopStarted ");
while(CONTINUE)
{
_current = DateTime.Now.Ticks / 1000;
if(_current > _last + (1000 / targetInputFPS))
{
_last = _current;
//Manage keyboard Input
this.cki = Console.ReadKey(true);
//Console.Write(":");
if(this.cki.Key == ConsoleKey.Q)
{
//MessageBox.Show("'Q' was pressed.");
CONTINUE = false;
}
if(this.cki.Key == ConsoleKey.P)
{
this.Pause();
}
if(this.cki.Key == ConsoleKey.R)
{
this.Resume();
}
}
else
{
System.Threading.Thread.Sleep(10);
}
}
}
public static void Main(string[] args)
{
TestLoops test = new TestLoops();
}
}
This is the solution I came up with to pause/resume an active thread inside a console...
It requires a second thread for input, which the main loop reacts too. But my ignorance of C# makes me wonder if there is a simpler solution? Perhaps one that can be done with the main thread alone?
Essentially, I am testing several things that will iterate at the defined FPS, and I want to be able to pause and resume the iteration via keyboard input. Any feedback is appreciated.
class TestLoops
{
int targetMainFPS = 5;
int targetInputFPS = 3;
bool CONTINUE = true;
Thread testLoop, testLoop2;
ConsoleKeyInfo cki;
ManualResetEvent resetThread = new ManualResetEvent(true); //How to correctly pause threads in C#.
public void Resume() { resetThread.Set(); }
public void Pause() { resetThread.Reset(); }
public TestLoops()
{
//_start = DateTime.Now.Ticks;
Console.Write("CreatingLoop...");
this.testLoop = new Thread(MainLoop);
this.testLoop.Start();
this.testLoop2 = new Thread(InputLoop);
this.testLoop2.Start();
}
void MainLoop()
{
long _current = 0;
long _last = 0;
Console.Write("MainLoopStarted ");
while(CONTINUE)
{
resetThread.WaitOne();
_current = DateTime.Now.Ticks / 1000;
if(_current > _last + (1000 / targetMainFPS) )
{
_last = _current;
//Do something...
Console.Write(".");
}
else
{
System.Threading.Thread.Sleep(10);
}
}
}
void InputLoop()
{
long _current = 0;
long _last = 0;
Console.Write("InputLoopStarted ");
while(CONTINUE)
{
_current = DateTime.Now.Ticks / 1000;
if(_current > _last + (1000 / targetInputFPS))
{
_last = _current;
//Manage keyboard Input
this.cki = Console.ReadKey(true);
//Console.Write(":");
if(this.cki.Key == ConsoleKey.Q)
{
//MessageBox.Show("'Q' was pressed.");
CONTINUE = false;
}
if(this.cki.Key == ConsoleKey.P)
{
this.Pause();
}
if(this.cki.Key == ConsoleKey.R)
{
this.Resume();
}
}
else
{
System.Threading.Thread.Sleep(10);
}
}
}
public static void Main(string[] args)
{
TestLoops test = new TestLoops();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用非阻塞
Console 极大地简化它.KeyAvailable
检查。这样,您就可以从主线程执行所有代码:编辑:回复评论。
当心。下面的代码由于
Console.ReadKey
调用而阻塞,而不是由于while
循环。while
循环的存在只是为了,如果用户输入除R
之外的字符,程序将丢弃它并等待输入另一个字符。如果您想阻止直到按下任何字符,您只需使用:
You can simplify it drastically by using the non-blocking
Console.KeyAvailable
check. That way, you can execute all your code from the main thread:Edit: Replying to comment.
Be careful. The code below blocks due to the
Console.ReadKey
call, not due to thewhile
loop. Thewhile
loop is there only so that, if the user enters a character other thanR
, the program would discard it and wait for another character to be entered.If you wanted to block until any character is pressed, you would simply use:
这会起作用,是的。您唯一可以考虑的事情是确保工作线程停止,即使它之前已暂停,当您按 Q 键时:
作为旁注,恒定的 FPS 通常由 维持适当地跳过帧,而不是暂停线程。暂停线程是不精确的,并且不允许微调动画速度。 Thread.Sleep 在不同硬件上的表现也可能不同,并且分辨率可能相当差(最小操作系统时间片约为 16ms IIRC)。
This will work, yes. The only thing that you could consider is making sure that the worker thread stops even if it was previously suspended, when you press the
Q
key:As a side note, constant FPS is usually maintained by skipping frames as appropriate, rather than pausing a thread. Pausing a thread is imprecise, and doesn't allow fine tuning animation speeds.
Thread.Sleep
can also behave differently on different hardware, and can have rather poor resolutions (a minimum OS timeslice is around ~16ms IIRC).