10

我怎样才能停止System.Threading.Timer它的回调方法。我参考MSDN了,但找不到任何有用的东西。请帮忙。

4

6 回答 6

15

首先,回调方法必须在范围内包含计时器实例。

然后是简单的咒语

timerInstance.Change( Timeout.Infinite , Timeout.Infinite ) ;

将关闭计时器。我相信,计时器可能会在更改后再次调用回调方法,具体取决于它所处的状态。

于 2012-08-13T16:41:29.537 回答
4
timer.Change(Timeout.Infinite, Timeout.Infinite);
于 2012-08-13T16:36:10.313 回答
2

尝试这个:

如果您愿意,可以让计时器继续触发回调方法并包含以下代码

private void CreatorLoop(object state)  
 { 
   if (Monitor.TryEnter(lockObject) 
   { 
     try 
     { 
       // Work here 
     } 
     finally 
     { 
       Monitor.Exit(lockObject); 
     } 
   } 
 } 

也请查看此链接:

在其回调方法中停止计时器

于 2012-08-13T16:38:52.977 回答
1

我发现 Change(Timeout.Infinite, Timeout.Infinite) 不太可靠,并在 AutoReset = false 的情况下切换到 System.Timers.Timer。

于 2013-05-23T12:36:53.307 回答
1

您可以简单地调用myTimer.Change(Timeout.Infinite, Timeout.Infinite).

dueTime从技术上讲,只需要指定第一个参数 ( ) 即可Timeout.Infinite让计时器停止。

有关详细信息,请参阅Timer.Change 方法

于 2012-08-13T16:36:55.807 回答
1

Timer 的问题在于它可能在释放其所有者类之后被调用。以下实现通过使用 Timer 初始化程序的状态对象为我工作。堆在消耗之前不会删除该对象。这是我优雅地清理计时器回调的唯一方法。

using System;
using System.Threading;

namespace TimerDispose
{
    /// <summary>
    /// A timer-containing class that can be disposed safely by allowing the timer 
    /// callback that it must exit/cancel its processes
    /// </summary>
    class TimerOwner : IDisposable
    {
        const int dueTime = 5 * 100;       //halve a second
        const int timerPeriod = 1 * 1000;   //Repeat timer every one second (make it Timeout.Inifinite if no repeating required)

        private TimerCanceller timerCanceller = new TimerCanceller();

        private Timer timer;

        public TimerOwner()
        {
            timerInit(dueTime);
        }

        byte[] dummy = new byte[100000];

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dueTime">Pass dueTime for the first time, then TimerPeriod will be passed automatically</param>
        private void timerInit(int dueTime)
        {

            timer = new Timer(timerCallback,
                timerCanceller,     //this is the trick, it will be kept in the heap until it is consumed by the callback 
                dueTime,
                Timeout.Infinite
            );

        }

        private void timerCallback(object state)
        {
            try
            {
                //First exit if the timer was stoped before calling callback. This info is saved in state
                var canceller = (TimerCanceller)state;
                if (canceller.Cancelled)
                {
                    return; //
                }

                //Your logic goes here. Please take care ! the callback might have already been called before stoping the timer
                //and we might be already here after intending of stoping the timer. In most cases it is fine but try not to consume
                //an object of this class because it might be already disposed. If you have to do that, hopefully it will be catched by
                //the ObjectDisposedException below




                dummy[1] = 50;  //just messing up with the object after it might be disposed/nulled

                //Yes, we need to check again. Read above note
                if (canceller.Cancelled)
                {
                    //Dispose any resource that might have been initialized above
                    return; //
                }

                if (timerPeriod != Timeout.Infinite)
                {
                    timerInit(timerPeriod);
                }
            }
            catch (ObjectDisposedException ex)
            {
                Console.WriteLine("A disposed object accessed");
            }
            catch (NullReferenceException ex)
            {
                Console.WriteLine("A nulled object accessed");
            }
            catch (Exception ex)
            {

            }
        }

        public void releaseTimer()
        {
            timerCanceller.Cancelled = true;
            timer.Change(Timeout.Infinite, Timeout.Infinite);
            timer.Dispose();
        }

        public void Dispose()
        {
            releaseTimer();
            dummy = null;   //for testing
            GC.SuppressFinalize(this);
        }
    }

    class TimerCanceller
    {
        public bool Cancelled = false;
    }


    /// <summary>
    /// Testing the implementation
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            var list = new System.Collections.Generic.List<TimerOwner>();
            Console.WriteLine("Started initializing");
            for (int i = 0; i < 500000; i++)
            {
                list.Add(new TimerOwner());
            }

            Console.WriteLine("Started releasing");
            foreach (var item in list)
            {
                item.Dispose();
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}
于 2017-06-16T19:28:52.310 回答