C# 定时器跳过代码
C# Timer Skips Code
我在构造函数中告诉定时器启动。它开始了,但是当它到达它的 Timer.Elapsed 事件时它只运行方法中的第一个 if 语句。我检查过 isWatching
是否为真,确实如此,但它仍然完全跳过它。它甚至没有到达 if(isWatching)
行。
代码:
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public SessionManager SM { get; private set; }
public MainWindow()
{
SM = new SessionManager();
SM.NewDayEvent += SplitSession;
///code
}
}
SessionManager.cs(此post中省略了一些变量):
public class SessionManager : INotifyPropertyChanged
{
public delegate void NewDayEventHandler(object sender, EventArgs ea);
public event NewDayEventHandler NewDayEvent;
private bool _isWatching;
private Timer _timer;
private bool isWatching
{
get
{
return _isWatching;
}
set
{
_isWatching = value;
if (!_isWatching)
{
_clockWatch.Stop();
}
else
{
_clockWatch.Start();
}
}
}
#endregion
public SessionManager()
{
_clockWatch = new Stopwatch();
_timer = new Timer(1000);
_timer.Elapsed += timerElapsed;//focus on this here
_isWatching = false;
current_time = new DateTime();
CurrentTime = DateTime.Now;
_timer.Start();
}
public void timerElapsed(object sender, ElapsedEventArgs e)
{
CurrentTime = DateTime.Now;
if (CurrentTime.TimeOfDay == TimeSpan.Parse("9:32 AM") && NewDayEvent != null)
{
NewDayEvent(this, new EventArgs());
}
if (isWatching)
{
if (CurrentSession != null)
{
//update the timespent variable of the current timeEntry
if (CurrentSession.currentTimeEntry != null)
{
CurrentSession.currentTimeEntry.TimeSpent = _clockWatch.Elapsed;
calculateTotalTime();
CalculateFilteredTimeSpent();
}
}
}
}
}
您在调用 TimeSpan.Parse()
时使用的格式不正确。做你想做的事情的正确方法是:
TimeSpan.Parse("9:32")
您当前的代码片段抛出 System.FormatException
:
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
但是对于你想要达到的目标,每天在特定时间触发一次动作,上述方法可能不是最好的,因为它成功的机会非常小。计时器将每 1000 毫秒 运行,然后 return 包含毫秒的当前时间。因此可以在 9:32.0001 处调用计时器已用事件,并且可能永远不会通过该条件。更好的选择可能是:
if (CurrentTime.TimeOfDay >= TimeSpan.Parse("9:32") && NewDayEvent != null)
这将在该时间过去后触发不止一次,因此您可以添加一个标志来跟踪最后一个事件的处理日期。
或者,您也可以查看 .NET 4.5 中的 ScheduleAction 或一些解决方案 here。
我在构造函数中告诉定时器启动。它开始了,但是当它到达它的 Timer.Elapsed 事件时它只运行方法中的第一个 if 语句。我检查过 isWatching
是否为真,确实如此,但它仍然完全跳过它。它甚至没有到达 if(isWatching)
行。
代码:
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public SessionManager SM { get; private set; }
public MainWindow()
{
SM = new SessionManager();
SM.NewDayEvent += SplitSession;
///code
}
}
SessionManager.cs(此post中省略了一些变量):
public class SessionManager : INotifyPropertyChanged
{
public delegate void NewDayEventHandler(object sender, EventArgs ea);
public event NewDayEventHandler NewDayEvent;
private bool _isWatching;
private Timer _timer;
private bool isWatching
{
get
{
return _isWatching;
}
set
{
_isWatching = value;
if (!_isWatching)
{
_clockWatch.Stop();
}
else
{
_clockWatch.Start();
}
}
}
#endregion
public SessionManager()
{
_clockWatch = new Stopwatch();
_timer = new Timer(1000);
_timer.Elapsed += timerElapsed;//focus on this here
_isWatching = false;
current_time = new DateTime();
CurrentTime = DateTime.Now;
_timer.Start();
}
public void timerElapsed(object sender, ElapsedEventArgs e)
{
CurrentTime = DateTime.Now;
if (CurrentTime.TimeOfDay == TimeSpan.Parse("9:32 AM") && NewDayEvent != null)
{
NewDayEvent(this, new EventArgs());
}
if (isWatching)
{
if (CurrentSession != null)
{
//update the timespent variable of the current timeEntry
if (CurrentSession.currentTimeEntry != null)
{
CurrentSession.currentTimeEntry.TimeSpent = _clockWatch.Elapsed;
calculateTotalTime();
CalculateFilteredTimeSpent();
}
}
}
}
}
您在调用 TimeSpan.Parse()
时使用的格式不正确。做你想做的事情的正确方法是:
TimeSpan.Parse("9:32")
您当前的代码片段抛出 System.FormatException
:
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
但是对于你想要达到的目标,每天在特定时间触发一次动作,上述方法可能不是最好的,因为它成功的机会非常小。计时器将每 1000 毫秒 运行,然后 return 包含毫秒的当前时间。因此可以在 9:32.0001 处调用计时器已用事件,并且可能永远不会通过该条件。更好的选择可能是:
if (CurrentTime.TimeOfDay >= TimeSpan.Parse("9:32") && NewDayEvent != null)
这将在该时间过去后触发不止一次,因此您可以添加一个标志来跟踪最后一个事件的处理日期。
或者,您也可以查看 .NET 4.5 中的 ScheduleAction 或一些解决方案 here。