0

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
    }
4

2 に答える 2

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
    }
于 2012-04-28T13:41:46.073 に答える
0
  1. クラスのどこかにタイマー(またはタイマーを参照するクラス)への参照を保存する必要があります。
  2. タイマーを停止するために、それを破棄する必要はありません。を呼び出すだけtimer.Change(-1, -1);です。これにより、タイマーを再度有効にすることができますtimer.Change(dueTimeInMs, intervalInMs);

コードは次のようになります。

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また、タイマー間隔よりも長く実行される可能性がある場合は、そのメソッドが複数のスレッドで同時に実行されることに注意してください。これを回避するには、タイマーの間隔を使用しないでdueTimeください。代わりに次を使用します。

   private Timer timer = new Timer(o => {
                                         DoSomething(); 
                                         StartTimer();
                                         });

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

このタイマーでは、1 回だけ実行するようにトリガーされますが、各実行後に再トリガーされます。

于 2012-04-28T13:43:23.260 に答える