线程中的定时器如何结束

时间:2020-12-02 00:08:26

        static void Main(string[] args)
        {
            Thread ThrdA = new Thread(FunA);
            ThrdA.Start();
            Console.ReadLine();
        }
        public static void FunA()
        {
            Timer timerA = new Timer(new TimerCallback(A), null,0, 3000);
        }
        public static void A(object a)
        {
             Console.WriteLine("{0}", Thread.CurrentThread.ManagedThreadId);
        }

这样的代码会一直正常输出Thread.CurrentThread.ManagedThreadId的值;

        static void Main(string[] args)
        {
            Thread AThrd = new Thread(AutoAddFun);
            Thread RThrd = new Thread(AutoReadFun);
            AThrd.Start();
            RThrd.Start();
            Console.ReadLine();
        }

        static List<int> numList = new List<int>();

        static ReaderWriterLock rwl = new ReaderWriterLock();

        public static void AutoAddFun()
        {
            Timer timerAdd = new Timer(new TimerCallback(Add), null, 0, 3000);
        }

        public static void AutoReadFun()
        {
            Timer timerRead1 = new Timer(new TimerCallback(Read), null, 0, 1000);
            Timer timerRead2 = new Timer(new TimerCallback(Read), null, 0, 1000);
            Timer timerRead3 = new Timer(new TimerCallback(Read), null, 0, 1000);
        }

        public static void Add(object obj)
        {
            var num = new Random().Next(0, 1000);

            rwl.AcquireWriterLock(TimeSpan.FromSeconds(30));

            numList.Add(num);

            Console.WriteLine("我是线程{0},我插入的数据是{1}。", Thread.CurrentThread.ManagedThreadId, num);

            rwl.ReleaseWriterLock();
        }

        public static void Read(object obj)
        {
            rwl.AcquireReaderLock(TimeSpan.FromSeconds(30));

            Console.WriteLine("我是线程{0},我读到的集合是{1}.", Thread.CurrentThread.ManagedThreadId, string.Join(",", numList));

            rwl.ReleaseReaderLock();
        }

这是@一线码农 的源码,讲解ReadWriterLock方面的知识点,运行代码一段时间后会停止输出,在所有定时器的回调函数中打了断点均没有中断,说明定时器已经停止了,在上下文中并没有主动将定时器停止,我想请问这个过程大概是怎样的。谢谢。

9 个解决方案

#1


线程中的定时器如何结束浮起来!

#2


线程中的定时器如何结束麻里麻里哄

#3


线程中的定时器如何结束锲而不舍

#4


你确定这个代码是终止掉了,而不是进入死锁了?

#5


所谓死锁,就是Add在等待Read,同时Read也在等待Add

#6


凑巧而已,你测试时你的Timer正好没有被垃圾回收

试试改成这样,说不定Timer就不会继续跑了:
            var ThrdA = new Thread(FunA);
            ThrdA.Start();
            for (int i = 0; i < 10; i++)
            {
                var s = new int[100000000];
            }
            Console.ReadLine();

#7


引用 4 楼 Z65443344 的回复:
你确定这个代码是终止掉了,而不是进入死锁了?


        public static void Add(object obj)
        {
            var num = new Random().Next(0, 1000);
            try
            {
                rwl.AcquireWriterLock(TimeSpan.FromSeconds(30));
                try
                {
                    numList.Add(num);

                    Console.WriteLine("我是线程{0},我插入的数据是{1}。", Thread.CurrentThread.ManagedThreadId, num);
                }
                finally
                {
                    rwl.ReleaseWriterLock(); 
                }
            }
            catch (ApplicationException)
            {
                rwl.ReleaseWriterLock();
            }
        }

我修改了部分代码(同样修改了Read部分),如果死锁,请求便超时,同时抛出ApplicationException异常,实际上并没有抛出异常。所以,我想应该不是死锁的问题。 线程中的定时器如何结束

#8


原因很简单,计时器被GC了。在MSDN里有一段话:

只要在使用 Timer,就必须保留对它的引用。 对于任何托管对象,如果没有对 Timer 的引用,计时器会被垃圾回收。 即使 Timer 仍处在活动状态,也会被回收。

http://msdn.microsoft.com/zh-cn/library/system.threading.timer(v=vs.110).aspx

#9


引用 8 楼 effun 的回复:
只要在使用 Timer,就必须保留对它的引用。 对于任何托管对象,如果没有对 Timer 的引用,计时器会被垃圾回收。 即使 Timer 仍处在活动状态,也会被回收。

是呀,@phommy的评论提醒了我往GC方面想,在@teof的博客上看到上面那句话,豁然开朗!
而且,回调方法不在创建计时器的线程上执行,而是在系统提供的ThreadPool线程上执行。呵呵 线程中的定时器如何结束

#1


线程中的定时器如何结束浮起来!

#2


线程中的定时器如何结束麻里麻里哄

#3


线程中的定时器如何结束锲而不舍

#4


你确定这个代码是终止掉了,而不是进入死锁了?

#5


所谓死锁,就是Add在等待Read,同时Read也在等待Add

#6


凑巧而已,你测试时你的Timer正好没有被垃圾回收

试试改成这样,说不定Timer就不会继续跑了:
            var ThrdA = new Thread(FunA);
            ThrdA.Start();
            for (int i = 0; i < 10; i++)
            {
                var s = new int[100000000];
            }
            Console.ReadLine();

#7


引用 4 楼 Z65443344 的回复:
你确定这个代码是终止掉了,而不是进入死锁了?


        public static void Add(object obj)
        {
            var num = new Random().Next(0, 1000);
            try
            {
                rwl.AcquireWriterLock(TimeSpan.FromSeconds(30));
                try
                {
                    numList.Add(num);

                    Console.WriteLine("我是线程{0},我插入的数据是{1}。", Thread.CurrentThread.ManagedThreadId, num);
                }
                finally
                {
                    rwl.ReleaseWriterLock(); 
                }
            }
            catch (ApplicationException)
            {
                rwl.ReleaseWriterLock();
            }
        }

我修改了部分代码(同样修改了Read部分),如果死锁,请求便超时,同时抛出ApplicationException异常,实际上并没有抛出异常。所以,我想应该不是死锁的问题。 线程中的定时器如何结束

#8


原因很简单,计时器被GC了。在MSDN里有一段话:

只要在使用 Timer,就必须保留对它的引用。 对于任何托管对象,如果没有对 Timer 的引用,计时器会被垃圾回收。 即使 Timer 仍处在活动状态,也会被回收。

http://msdn.microsoft.com/zh-cn/library/system.threading.timer(v=vs.110).aspx

#9


引用 8 楼 effun 的回复:
只要在使用 Timer,就必须保留对它的引用。 对于任何托管对象,如果没有对 Timer 的引用,计时器会被垃圾回收。 即使 Timer 仍处在活动状态,也会被回收。

是呀,@phommy的评论提醒了我往GC方面想,在@teof的博客上看到上面那句话,豁然开朗!
而且,回调方法不在创建计时器的线程上执行,而是在系统提供的ThreadPool线程上执行。呵呵 线程中的定时器如何结束