从另一个类中取消线程计时器

时间:2012-04-28 13:12:52

标签: c# wpf timer

我正在尝试在我自己的代码中为Thread.Timers实现MSDN示例(http://msdn.microsoft.com/en-us/library/swx5easy.aspx)。

我希望能够在执行某个用户操作时取消计时器,但是我无法处理计时器,我怀疑这是因为我从另一个类调用一个方法所以我需要调整;但我不知道在哪里。

除此之外,计时器工作正常。任何人都可以看到为什么我的计时器在调用btnconfigOpenConfig时不会取消?

仅供参考我正在将工作流程转换为定时事件。

public partial class Xservt : Window
        {

            internal class TimerStateObjClass
            {
                public int SomeValue;
                public System.Threading.Timer SqlUpdateFromTwitterTimerReference;
                public bool TimerCanceled;
            }


internal void SomeMethod(){


                    TimerStateObjClass stateObj = new TimerStateObjClass();
                    stateObj.TimerCanceled = false;
                    stateObj.SomeValue = 100;
                    System.Threading.TimerCallback timerDelegate =
                        new System.Threading.TimerCallback(twit.hometimelineclass._sqlUpdateFromTwitterWorker_DoWork);

                    var sqlUpdateFromTwitterTimer = new Timer(timerDelegate, stateObj, 0,20000);
                    stateObj.SqlUpdateFromTwitterTimerReference = sqlUpdateFromTwitterTimer;

    }
}


//action to perform which disposes the timer
private void btnconfigOpenConfig(object sender, RoutedEventArgs e)
            {

                TimerStateObjClass timerState = new TimerStateObjClass();
                timerState.TimerCanceled = true;
    }


//Actions the timer is calling, in another class
internal static void _sqlUpdateFromTwitterWorker_DoWork(object StateObj)
            {

                Xservt.TimerStateObjClass state = (Xservt.TimerStateObjClass) StateObj;

                if(state.TimerCanceled)
                {
                    state.SqlUpdateFromTwitterTimerReference.Dispose();

                }

    //some work
    }

2 个答案:

答案 0 :(得分:0)

正如Hans在评论中指出的那样,您需要保留对最初创建的TimerStateObjClass的引用。然后,您可以使用它来设置TimerCanceled。

public partial class Xservt : Window
{

    internal class TimerStateObjClass
    {
        public int SomeValue;
        public System.Threading.Timer SqlUpdateFromTwitterTimerReference;
        public bool TimerCanceled;
    }

    TimerStateObjClass stateObj;  //THIS IS THE ORIGINAL STATE OBJ
    internal void SomeMethod()
    {
        stateObj = new TimerStateObjClass();
        stateObj.TimerCanceled = false;
        stateObj.SomeValue = 100;
        System.Threading.TimerCallback timerDelegate = new System.Threading.TimerCallback(twit.hometimelineclass._sqlUpdateFromTwitterWorker_DoWork);

        var sqlUpdateFromTwitterTimer = new Timer(timerDelegate, stateObj, 0, 20000);
        stateObj.SqlUpdateFromTwitterTimerReference = sqlUpdateFromTwitterTimer;
    }

    //action to perform which disposes the timer
    private void btnconfigOpenConfig(object sender, RoutedEventArgs e)
    {
        //HERE WE CAN GET AT THE ORIGINAL STATE OBJ
        stateObj.TimerCanceled = true;
    }
}
    //Actions the timer is calling, in another class
    internal static void _sqlUpdateFromTwitterWorker_DoWork(object StateObj)
    {
        Xservt.TimerStateObjClass state = (Xservt.TimerStateObjClass)StateObj;

        if (state.TimerCanceled)
        {
            state.SqlUpdateFromTwitterTimerReference.Dispose();
        }

        //some work
    }

答案 1 :(得分:0)

  1. 您需要在班级的某个地方存储对计时器(或引用计时器的类)的引用。
  2. 要停止计时器,不需要处理它。您只需拨打timer.Change(-1, -1);即可。这将允许通过调用timer.Change(dueTimeInMs, intervalInMs);
  3. 再次重新启用计时器

    您的代码应该是这样的:

    public partial class Xservt : Window
    {
       private Timer timer = new Timer(o => DoSomething());
    
       private void StartTimer()
       {
         var period = 5 * 1000; // 5 sec
         timer.Change(0, period);
       }
    
       private void StopTimer()
       {
         timer.Change(-1, -1);
       }
    }
    

    然后调用StartTimer运行它,StopTimer分别停止。

    另请注意,如果DoSomething的运行时间超过计时器间隔,则会导致同时在多个线程中运行该方法。为避免这种情况,请勿使用Timer的间隔,而是使用dueTime代替:

       private Timer timer = new Timer(o => {
                                             DoSomething(); 
                                             StartTimer();
                                             });
    
       private void StartTimer()
       {
         var period = 5 * 1000; // 5 sec
         timer.Change(period, 0);
       }
    

    在此计时器中,trigrred只运行一次,但每次运行后都会重新触发。