我正在编写一个简单的“ Score Attack”扑克游戏。玩家在计时器滴答作响时组装值得打分的扑克手。我的问题是游戏过度。
我的游戏逻辑在一个线程中运行,因为游戏本身非常简单。我需要知道如何终止该线程,而播放器不再能够输入。我在MSDN上已经读到,执行此操作的安全方法是使用循环使线程的方法返回并结束线程。我遇到的问题是我的游戏需要用户输入,而用户输入会导致在计时器滴答为零时不检查循环。
到目前为止,该代码使用Thread.Abort(),并且可以正常工作,但是根据我在此站点上的搜索,这通常被认为是一个坏主意。有什么方法可以设置一个条件,以安全地终止线程,而不管所述线程中需要输入什么方法? (Console.ReadLine())
中止线程的游戏循环和计时器回调的代码:
private void GameLoop()
{
double stash = 0;
while (true)
{
player.SwapCards(gameDeck);
Table.WriteInfo("Stash This Hand? y/n");
if (Console.ReadLine().Equals("y"))
{
countdown += (int)ScoreHand(player.Hand);
stash += ScoreHand(player.Hand);
BankHand();
}
}
}
private void TimeDrop(object state)
{
countdown--;
Debug.WriteLine(countdown);
if (countdown == 0)
{
GameThread.Abort();
GameOverThread.Start();
Timer.Dispose();
}
}
在它坐着的时候,循环一直运行到线程中止为止。
编辑:
根据请求,代码将启动线程:
public Game()
{
gameDeck = new Deck();
InitPlayer();
DealHand();
countdown = 60;
GameThread = new Thread(GameLoop);
GameOverThread = new Thread(GameOver);
Timer = new Timer(new TimerCallback(TimeDrop), null, 0, 1000);
Timer.Change(0, 1000); //Ensures timer won't be garbage collected
GameThread.Start();
}
答案 0 :(得分:0)
使用async / await而不是线程可以更轻松,更干净地实现这种事情。
首先,我们需要使用可取消(和异步)的方法包装阻塞控制台输入法。该方法使用KeyAvailable
轮询控制台,并在检查CancellationToken
时异步延迟。
public static async Task<ConsoleKeyInfo> ReadKeyAsync(CancellationToken cancellationToken)
{
while (!Console.KeyAvailable)
{
await Task.Delay(100, cancellationToken);
}
return Console.ReadKey();
}
现在,我们可以启动此异步方法,并从CancellationTokenSource
传递取消令牌,该令牌将在特定时间(例如10秒)后自动取消。
public static async Task Main(string[] args)
{
Console.WriteLine("You have 10 seconds to press the Y key...");
var cts = new CancellationTokenSource(10_000);
try
{
while (true)
{
var key = await ReadKeyAsync(cts.Token);
if (key.Key == ConsoleKey.Y)
{
Console.WriteLine("Good job!");
break;
}
else
{
Console.WriteLine("Wrong Key");
}
}
}
catch (OperationCanceledException)
{
Console.Write("Time up!");
}
}