立即安全地终止线程 (C#)
Posted
技术标签:
【中文标题】立即安全地终止线程 (C#)【英文标题】:Terminating a thread immediately and safely (C#) 【发布时间】:2019-05-03 13:35:58 【问题描述】:我正在编写一个简单的“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();
【问题讨论】:
你能展示创建游戏线程的代码吗? 中止线程几乎总是一个坏主意。您可以询问Console
是否有可用的密钥以短暂睡眠,而不是阻止ReadLine
呼叫。
@Flydog57 我不确定你的意思。您能否指出您所指的功能或技术?
您需要做的是向另一个线程发送消息并让它自然终止。只有当您试图从您的应用程序中崩溃时,才应拨打任何对Thread.Abort()
的电话。在所有其他情况下,不要调用它。
【参考方案1】:
使用 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!");
【讨论】:
以上是关于立即安全地终止线程 (C#)的主要内容,如果未能解决你的问题,请参考以下文章