我正在尝试倒计时!
这是我尝试过的计时器代码:
a.find()
但是,我希望我的代码倒数秒,并且在输出中仅使用一行。
我正在尝试倒计时!
这是我尝试过的计时器代码:
class WorkingWithTimer
{
public static int input()
{
int numberOfSeconds;
do
{
Console.WriteLine("How many seconds would you like the test to be? Please type a number divisible by 10!");
int.TryParse(Console.ReadLine(), out numberOfSeconds);
} while (numberOfSeconds % 10 != 0);
return numberOfSeconds;
}
public static void CountTimer(object time)
{
Console.WriteLine($"TimeLeft: {time}");
Thread.Sleep(1000);
}
public static void Main(string[] args)
{
int numberOfSeconds = input();
Timer t = new Timer(CountTimer, numberOfSeconds, 1, 1000);
Thread.Sleep(1000);
t.Dispose();
}
}
但是,我希望我的代码在不创建换行符的情况下倒计时,例如将10更改为第一行的9,以此类推。
答案 0 :(得分:2)
如果我对您使用的自定义Timer类的推论是正确的,则它是:
因为它始终需要向您提供相同的对象,所以您需要稍微更改代码,以便传递的对象不是值类型;如果不这样做,则将递减CountTimer中的int,但不会有任何变化,因为您不会修改原始引用所指向的数据。您可能不能只添加ref关键字,因为自定义计时器不会被编程为使用它来调用。因此,让我们对其进行调整,以便我们传递一个int数组:
public static void CountTimer(object time)
{
var x = (int[])time;
x[0]--;
Console.WriteLine($"TimeLeft: {x[0]}");
//Thread.Sleep(1000); you don't need to sleep for a second; it will make your timer count every two seconds!
}
public static void Main(string[] args)
{
int[] numberOfSeconds = new int[1];
numberOfSeconds[0] = input();
Timer t = new Timer(CountTimer, numberOfSeconds, 1, 1000);
Thread.Sleep(1000);
t.Dispose();
}
如上所述,所有这些取决于您的Timer类,其中有一些自定义类,该类采用方法名称来每x毫秒调用一次,并始终为它提供相同的对象。没有任何地方会减少您的int时间,因此它一次又一次地说了30。我们不能像您一样将time
强制转换为一个int并递减它,因为它不会导致Timer保留的原始int发生变化。取而代之的是,如果让它使Timer持有的对象是一个int数组,那么该数组对象本身就不会改变,但是存储在第一个插槽中的值可以递减
FWIW,我认为这是创建倒数计时器的一种非常复杂的方法,并且也阻碍了用户执行其他任何操作。如果这很适合您的游戏,那么很好,但是如果您希望他们在30秒内采取行动,那么我认为您正在使用的Timer类会遇到麻烦
答案 1 :(得分:1)
由于您使用的是System.Threading.Timer
和控制台应用程序,因此您将需要一种告诉控制台应用程序等待定时器完成的方法。调用Thread.Sleep(1000);
不会削减它-特别是因为您正在等待至少10秒。
使控制台应用程序等待的简单方法是使用AutoResetEvent
。
private static AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
现在您可以在_autoResetEvent.WaitOne();
方法中调用Main
,它将等待直到您在_autoResetEvent.Set();
方法中调用CountTimer
。
现在,使用System.Threading.Timer
,您可以在构造计时器时传递状态,但是该状态不会更新,因此您需要添加另一个字段来跟踪秒数滴答作响的。
private static int _numberOfSeconds = 0;
此外,当您在框架中花费时间做任何事情,并且可以选择传递int
或使用TimeSpan
之间时,应始终选择TimeSpan
,因为这会使您的代码更复杂更具可读性。
您的Main
和CountTimer
方法现在看起来像这样:
public static void Main(string[] args)
{
_numberOfSeconds = input();
using (var t = new Timer(CountTimer, null, TimeSpan.Zero, TimeSpan.FromSeconds(1.0)))
{
//Thread.Sleep(1000); No Need To Sleep Here!
_autoResetEvent.WaitOne();
}
_autoResetEvent.Dispose();
}
public static void CountTimer(object state)
{
Console.WriteLine($"TimeLeft: {_numberOfSeconds--}");
//Thread.Sleep(1000); No Need To Sleep Here!
if (_numberOfSeconds < 0)
{
_autoResetEvent.Set();
}
}
请注意,由于示例代码没有真实状态,因此我将null
传递为Timer
的状态。
使用10
输入运行此代码时得到的输出是:
How many seconds would you like the test to be? Please type a number divisible by 10!
TimeLeft: 10
TimeLeft: 9
TimeLeft: 8
TimeLeft: 7
TimeLeft: 6
TimeLeft: 5
TimeLeft: 4
TimeLeft: 3
TimeLeft: 2
TimeLeft: 1
TimeLeft: 0
答案 2 :(得分:-1)
您应该查看this以获得更多信息。基本上,您可以这样做:
class StatusChecker {
private int numberOfSecondsLeft;
public StatusChecker(int numberOfSecondsLeft) {
this.numberOfSecondsLeft = numberOfSecondsLeft;
}
public void CountDown(object state) {
Console.Write($"{this.numberOfSecondsLeft},");
var autoEvent = (AutoResetEvent)state;
if (--this.numberOfSecondsLeft == 0) {
autoEvent.Set();
}
}
}
class Program {
static void Main(string[] args) {
var numberOfSeconds = input();
var autoEvent = new AutoResetEvent(false);
var checker = new StatusChecker(numberOfSeconds);
Console.WriteLine("Time left:");
var t = new Timer(checker.CountDown, autoEvent, 0, 1000);
autoEvent.WaitOne();
t.Dispose();
}
public static int input() {
int numberOfSeconds;
do {
Console.WriteLine("How many seconds would you like the test to be? Please type a number divisible by 10!");
int.TryParse(Console.ReadLine(), out numberOfSeconds);
} while (numberOfSeconds % 10 != 0);
return numberOfSeconds;
}
}