Dispatcher计时器发射两次:(

时间:2014-10-22 22:34:49

标签: c# wpf timer dispatchertimer

我有这个计时器的问题,我在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);
}

4 个答案:

答案 0 :(得分:2)

您要添加“ + = new EventHandler”,并在新的EventHandler上添加和添加新的EventHandler,但是永远不要删除它们。.

每次计时器重新启动时,都会触发所有先前的触发器。 如果实现了计数器,则可以重现此行为,那么您将看到,对于每个新添加和引发的Event,它都是两倍。 (编辑:只是因为“ new”关键字而感到困惑,但是实际上我不会删除答案,因为我很确定在某些情况下这确实是问题所在)

以下内容可能会有所帮助: How to remove all event handlers from an event

这是最简单的解决方案: (您可以使用委托人对其进行润色)

类中的声明:

VBA.Strings.Join

调度程序计时器方法:

private System.Windows.Threading.DispatcherTimer P5DispatcherHelpsystemTimer = new System.Windows.Threading.DispatcherTimer();
private EventHandler P5DispatcherTimerHandler;

调度程序TimerTick方法:

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);

(如果您遇到更复杂的情况,则肯定需要委托List <>)

答案 1 :(得分:0)

以下代码仅触发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);
            }
        }
    }
}

答案 2 :(得分:0)

我倾向于写我的&#34;一次性&#34;定时器代码如下:

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();

然后我不需要为制作新方法而烦躁 - 它只是在一个本地代码块中。

答案 3 :(得分:0)

对我来说,它根本没有启动,停止或计时器。 DI / IOC容器解析了ViewModel的两个实例,从而在构造函数中启动了一个新的刷新计时器。检查以确保始终看到相同的ViewModel实例,而不是实际上看到的是两个单独的实例,并触发两个单独的Timer。