我的计时器有问题,我在Tick事件中的函数出现了两次。。我希望它只出现一次。。
public void timerStart()
{
DispatcherTimer updaterTimer = new DispatcherTimer();
updaterTimer.Tick += new EventHandler(updaterTimer_Tick);
updaterTimer.Interval = new TimeSpan(0,0,0,0,300);
updaterTimer.Start();
}
private void updaterTimer_Tick(object sender, EventArgs e)
{
updaterTimer.Stop();
checkSigningAvailable();
updaterTimer.Start();
}
这是一种在计时器的每一次滴答声中都会检查的方法
public void checkSigningAvailable()
{
if (dt_signing_in.CompareTo(DateTime.Now) < 0)
{
if (!InPopAlready)
{
InPopAlready = true;
disableSigningIn("False", this.event_id);
}
}
}
在上调用该函数后,底部的消息框出现了两次
public void disableSigningIn(string Out,string event_id)
{
System.Console.WriteLine("POPED "+ InPopAlready);
connection.Open();
string sign = "True," + Out;
string query = "update data_storage set data_details = '" + sign + "' where data_name = 'Signing';";
NpgsqlCommand command = new NpgsqlCommand(query, connection);
command.ExecuteNonQuery();
connection.Close();
sign_in.Content = "Sign-in Time : Over";
string query2 = concatQuery(getIDnumberAttendance(event_id));
updateAbsences(query2);
MessageBox.Show("Signing in is over!", "No more signing in!", MessageBoxButton.OK, MessageBoxImage.Information);
}
您正在添加"+=new EventHandler",并在所有新的EventHandlers上添加新的EventHandler,但从未删除它们。。
每次计时器再次启动时,前面的所有计时器都会被激发。如果您实现了一个计数器,那么您可以重现这种行为,然后您将看到它与每个新添加和引发的事件一起翻倍。(编辑:只是因为"new"关键字而感到困惑,但实际上我不会删除答案,因为我很确定在某些情况下这将是问题所在)
以下内容可能会有所帮助:如何从事件中删除所有事件处理程序
这里是最简单的解决方案:(您可以使用代理人对其进行润色)
分类申报:
private System.Windows.Threading.DispatcherTimer P5DispatcherHelpsystemTimer = new System.Windows.Threading.DispatcherTimer();
private EventHandler P5DispatcherTimerHandler;
调度员计时器方法:
private void InitializeHelpsystemCronjobs(System.Windows.Controls.Canvas sub_CanvasElement)
{
P5DispatcherTimerHandler = (sender, e) => P5DispatcherHelpsystemTimerTick(sender, e, sub_CanvasElement);
P5DispatcherHelpsystemTimer.Tick += P5DispatcherTimerHandler;
P5DispatcherHelpsystemTimer.Interval = new TimeSpan(0, 0, 1);
P5DispatcherHelpsystemTimer.Start();
}
调度员时间选择方法:
private void P5DispatcherHelpsystemTimerTick(object sender, EventArgs e, System.Windows.Controls.Canvas sub_CanvasElement)
{
P5DispatcherHelpsystemTimer.Stop();
{
// Do stuff
}
P5DispatcherHelpsystemTimer.Start();
}
//当触发事件或动作等发生时,计时器应启动:
InitializeHelpsystemCronjobs(HelpsystemHelpCanvas);
//当它停止时的某个地方:
P5DispatcherHelpsystemTimer.Stop();
P5DispatcherHelpsystemTimer.Tick -= P5DispatcherTimerHandler;
(如果您有更复杂的情况,您肯定需要委托列表<>)
对我来说,它根本不是启动、停止或计时器。正是DI/IOC容器解析了ViewModel的两个实例,从而在构造函数中启动了一个新的刷新计时器。检查以确保始终看到相同的ViewModel实例,而不是实际看到的两个独立实例,即激发两个独立的Timer。
下面的代码只触发MessageBox一次:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.timerStart();
}
DispatcherTimer updaterTimer;
private bool InPopAlready;
DateTime dt_signing_in;
public void timerStart()
{
updaterTimer = new DispatcherTimer();
updaterTimer.Tick += new EventHandler(updaterTimer_Tick);
updaterTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);
updaterTimer.Start();
}
private void updaterTimer_Tick(object sender, EventArgs e)
{
updaterTimer.Stop();
checkSigningAvailable();
updaterTimer.Start();
}
public void checkSigningAvailable()
{
if (dt_signing_in.CompareTo(DateTime.Now) < 0)
{
if (!InPopAlready)
{
InPopAlready = true;
// Calling your method and showing MessageBox
MessageBox.Show("Signing in is over!", "No more signing in!", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
}
我倾向于这样写我的"一次性"计时器代码:
var updaterTimer = new DispatcherTimer();
updaterTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);
EventHandler tick = null;
tick = (s, e) =>
{
updaterTimer.Stop();
updaterTimer.Tick -= tick;
/* execute once-off code here */
};
updaterTimer.Tick += tick;
updaterTimer.Start();
那么我就不需要在制作新方法时搞砸了——这一切都在一个本地代码块中。