System.Threading.Timer 不执行回调,但不抛出错误
System.Threading.Timer doesnt execute its callback, but doesnt throw an error
我计划用 dotnet 创建一个命令行程序,它使用菜单让用户决定他们想玩什么游戏(我已经制作但没有实现 tictactoe,我正在尝试创建一个糟糕的游戏蛇版)然后播放它们。我有三个独立的 类,一个用于菜单,一个用于 Snake,一个用于 Tictactoe(未实现,未显示)。
对于贪吃蛇,我尝试过使用System.Threading.Timer不断刷新棋盘状态。
菜单 Class:
using System;
using System.Threading;
namespace Boolean_Operators
{
public class Menu
{
static Snake SnakeGame = new Snake();
// var Tictactoe = new Tictactoe();
static void Main(string[] args)
{
RunGame();
}
static void RunGame()
{
Timer refreshTimer = new Timer(SnakeGame.PrintBoard, null, 0, 1000);
if(SnakeGame.invokeCount == SnakeGame.maxCount)
{
refreshTimer.Dispose();
}
}
}
}
蛇Class:
using System;
using System.Threading;
namespace Boolean_Operators
{
public class Snake
{
public int invokeCount = 0;
public int maxCount = 20;
string[,] board = new string[,]{
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",}
};
public void PrintBoard(object state)
{
invokeCount++;
for(int i = 0; i <= 10; i++)
{
Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write($" {board[i, 0]} | {board[i, 1]} | {board[i, 2]} | {board[i, 3]} | {board[i, 4]} | {board[i, 5]} | {board[i, 6]} | {board[i, 7]} | {board[i, 8]} | {board[i, 9]} ");
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write("-----+-----+-----+-----+-----+-----+-----+-----+-----+-----");
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
}
Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write($" {board[9, 0]} | {board[9, 1]} | {board[9, 2]} | {board[9, 3]} | {board[9, 4]} | {board[9, 5]} | {board[9, 6]} | {board[9, 7]} | {board[9, 8]} | {board[9, 9]} ");
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
}
}
}
无论出于何种原因,所有代码似乎都在执行,但 PrintBoard 方法代码从未执行过,并且当 运行 程序没有任何反应时:
Console Output when running
我希望答案是我错过的非常明显的东西,因为我尝试了很多垃圾东西来试图绕过它。
在 RunGame
中,这些是步骤:
- 创建新计时器
- 0-N 个定时器回调(可能是 0 个)。
- 之后评估 if 语句,这将是错误的。
- 0-N 个定时器回调(可能是 0 个)。
- 退出程序
您的计时器永远不会有机会调用,或者即使有,也只会在程序退出前调用几次。
完成第 1 步后,您必须在 Main()
内等待。 Timer class documentation shows you a way to do that using AutoResetEvent
. Another way you could do that is to do a SpinWait.SpinUntil 调用。您可以将代码更改为
static void RunGame()
{
Timer refreshTimer = new Timer(SnakeGame.PrintBoard, null, 0, 1000);
SpinWait.SpinUntil(() => SnakeGame.invokeCount == SnakeGame.maxCount);
refreshTimer.Dispose();
}
这会阻止 Main()
,直到满足条件。
我计划用 dotnet 创建一个命令行程序,它使用菜单让用户决定他们想玩什么游戏(我已经制作但没有实现 tictactoe,我正在尝试创建一个糟糕的游戏蛇版)然后播放它们。我有三个独立的 类,一个用于菜单,一个用于 Snake,一个用于 Tictactoe(未实现,未显示)。
对于贪吃蛇,我尝试过使用System.Threading.Timer不断刷新棋盘状态。
菜单 Class:
using System;
using System.Threading;
namespace Boolean_Operators
{
public class Menu
{
static Snake SnakeGame = new Snake();
// var Tictactoe = new Tictactoe();
static void Main(string[] args)
{
RunGame();
}
static void RunGame()
{
Timer refreshTimer = new Timer(SnakeGame.PrintBoard, null, 0, 1000);
if(SnakeGame.invokeCount == SnakeGame.maxCount)
{
refreshTimer.Dispose();
}
}
}
}
蛇Class:
using System;
using System.Threading;
namespace Boolean_Operators
{
public class Snake
{
public int invokeCount = 0;
public int maxCount = 20;
string[,] board = new string[,]{
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ",}
};
public void PrintBoard(object state)
{
invokeCount++;
for(int i = 0; i <= 10; i++)
{
Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write($" {board[i, 0]} | {board[i, 1]} | {board[i, 2]} | {board[i, 3]} | {board[i, 4]} | {board[i, 5]} | {board[i, 6]} | {board[i, 7]} | {board[i, 8]} | {board[i, 9]} ");
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write("-----+-----+-----+-----+-----+-----+-----+-----+-----+-----");
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
}
Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write($" {board[9, 0]} | {board[9, 1]} | {board[9, 2]} | {board[9, 3]} | {board[9, 4]} | {board[9, 5]} | {board[9, 6]} | {board[9, 7]} | {board[9, 8]} | {board[9, 9]} ");
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
}
}
}
无论出于何种原因,所有代码似乎都在执行,但 PrintBoard 方法代码从未执行过,并且当 运行 程序没有任何反应时:
Console Output when running
我希望答案是我错过的非常明显的东西,因为我尝试了很多垃圾东西来试图绕过它。
在 RunGame
中,这些是步骤:
- 创建新计时器
- 0-N 个定时器回调(可能是 0 个)。
- 之后评估 if 语句,这将是错误的。
- 0-N 个定时器回调(可能是 0 个)。
- 退出程序
您的计时器永远不会有机会调用,或者即使有,也只会在程序退出前调用几次。
完成第 1 步后,您必须在 Main()
内等待。 Timer class documentation shows you a way to do that using AutoResetEvent
. Another way you could do that is to do a SpinWait.SpinUntil 调用。您可以将代码更改为
static void RunGame()
{
Timer refreshTimer = new Timer(SnakeGame.PrintBoard, null, 0, 1000);
SpinWait.SpinUntil(() => SnakeGame.invokeCount == SnakeGame.maxCount);
refreshTimer.Dispose();
}
这会阻止 Main()
,直到满足条件。