我有一个每秒运行的计时器,代码如下:
public MainWindow()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += new EventHandler(someEventHandler);
timer.Start();
}
private void someEventHandler(Object sender, EventArgs args)
{
TVMonitor TVMonitor = new TVMonitor();
if (TVMonitor.NeedsTurningOn())
{
Console.WriteLine("on");
TVCOM.SendCommand(SettingManager.GetTVCode("on") + Environment.NewLine);
}
}
在函数NeedsTurningOn()
中,我有以下内容:
public bool NeedsTurningOn()
{
var turnon = (from settings in context.SystemSettings
where settings.SystemSettingName == "TVOnTime"
select settings).First();
if (turnon.SystemSettingValue == String.Empty)
{
return false;
}
DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
Console.WriteLine("Turnontime: " + date);
Console.WriteLine("currenttim: " + DateTime.Now);
if (date != DateTime.Now)
{
Console.WriteLine("false");
return false;
}
else
{
Console.WriteLine("true");
return true;
}
}
现在在我用于调试的控制台中,我有以下输出:
...
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:07
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:08
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:09
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:10
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:11
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:12
false
...
为什么一旦日期相同,这仍然是假的而不是真的?
答案 0 :(得分:2)
这是因为DateTime变量的分辨率为1毫秒......您将其比较为具有1秒的分辨率。
尝试:
if (Math.Abs(date.Subtract(DateTime.Now).Milliseconds) < 1000) { ... }
您可以通过将1000更改为其他数字来调整匹配的分辨率... 500将检查date
是否在当前日期/时间的半秒内。
答案 1 :(得分:1)
你只比较每秒的时间 - 毫秒仍然是不同的(特别是假设你比较的开启时间很可能不使用毫秒)。要在第二个分辨率中进行比较,您可以执行以下操作:
DateTime currentTime = DateTime.Now;
currentTime = currentTime.AddMilliseconds(-currentTime.Millisecond);
答案 2 :(得分:1)
这里的其他答案指出了为什么你会看到你的行为;即两个DateTime变量的毫秒数不同。
我建议你让自己的病情更加灵活。您依赖于这样一个事实,即您的NeedsTurningOn
方法将在您在开启时间设置中配置的那一秒内执行。如果系统挂了一秒怎么办?您的代码可能会间歇性地错过打开的窗口。如果您决定将计时器的间隔从1000更改为5000怎么办?在这种情况下,您的代码在正确的秒数内只有大约1/5的执行机会。
我建议你的条件是这样的:
if (this.IsTurnedOn)
{
Console.WriteLine("false - already on");
return false;
}
else
{
DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
Console.WriteLine("Turnontime: " + date);
Console.WriteLine("currenttim: " + DateTime.Now);
if (date > DateTime.Now)
{
Console.WriteLine("false");
return false;
}
else
{
Console.WriteLine("true");
return true;
}
}
基本上,将一个IsTurnedOn
属性添加到您的TVMonitor类中以充当标记,以便您知道是否确实需要打开它。另外,将date != DateTime.Now
更改为date > DateTime.Now
,因为我假设您确实要确定的是配置的开启时间已经过去。
答案 3 :(得分:0)
也许你应该比较总秒数或类似的东西?我可以想象毫秒不同......
答案 4 :(得分:0)
尝试将时间写为date.Ticks
和DateTime.Now.Ticks
,您会明白原因。分辨率远小于一秒。
如果你想要第二个分辨率,你必须比较日,月,年,小时,分钟和秒。
single tick代表一百纳秒或一千万分之一秒。一毫秒内有10,000个刻度,所以你需要一台真正快速的计算机来匹配相同的刻度:)
答案 5 :(得分:0)
由于Date和TimeSpan包含的组件比秒更精细,即毫秒和刻度。
我建议比较TotalSeconds属性。
答案 6 :(得分:0)
解决我的问题:
感谢上面的所有帮助,我在日期比较之前将其添加到我的函数中:
DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
DateTime current = DateTime.Now;
current = current.AddMilliseconds(-current.Millisecond);
date = date.AddMilliseconds(-date.Millisecond);