gpt4 book ai didi

详解C#中的定时器Timer类及其垃圾回收机制

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章详解C#中的定时器Timer类及其垃圾回收机制由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

关于C# Timer类  在C#里关于定时器类就有3个 。

C# Timer使用的方法1.定义在System.Windows.Forms里 。

C# Timer使用的方法2.定义在System.Threading.Timer类里  " 。

C# Timer使用的方法3.定义在System.Timers.Timer类里 。

下面我们来具体看看这3种C# Timer用法的解释:

(1)System.Windows.Forms.Timer 。

应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或Delphi中的Timer控件,内部使用API  SetTimer实现的。它的主要缺点是计时不精确,而且必须有消息循环,Console  Application(控制台应用程序)无法使用。     (2)System.Timers.Timer 。

和System.Threading.Timer非常类似,它们是通过.NET  Thread  Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求.

(3)System.Timers.Timer还可以应用于WinForm,完全取代上面的Timer控件。它们的缺点是不支持直接的拖放,需要手工编码.

C# Timer用法实例 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
使用System.Timers.Timer类
 
System.Timers.Timer t = 
new System.Timers.Timer(10000);
//实例化Timer类,设置间隔时间为10000毫秒; 
t.Elapsed += 
new System.Timers.ElapsedEventHandler(theout);
//到达时间的时候执行事件; 
t.AutoReset = true ;
//设置是执行一次(false)还是一直执行(true); 
t.Enabled = true ;
//是否执行System.Timers.Timer.Elapsed事件; 
 
public void theout(
object source, 
System.Timers.ElapsedEventArgs e) 
 
   MessageBox.Show( "OK!" ); 
  }

  Timer的垃圾回收机制 通常我们需要定时执行一段任务的时候,我们就需要定时器,这时我们就可以使用c# System.Threading空间中的 Timer定时器;他是个异步定时器,时间到时每次都是在线程池中分配一个线程去执行任务。下面我们来看一个有趣的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Program
   {
     static void Main( string [] args)
     {
       Timer timer = new Timer(TimerCallback, null ,0,2000);
      
       Console.ReadLine();
     }
 
     private static void TimerCallback( object o)
     {
       Console.WriteLine( "in TimerCallback method" );
       GC.Collect();
 
      
     }
   }

当我们在debug模式下运行该段程序时,正如我们期盼的那样程序会每隔2秒钟执行该方法,打印出"in TimerCallback method”,而在release模式下执行的时候,只执行一次该方法,字符串只打印一次。在这里我们在调用TimerCallback方法时,强制执行垃圾回收器,说明在release模式下,垃圾回收器执行回收算法时,首先假设所有对象都是可回收的,当将Timer对象赋值给变量t后,t没有在被引用,因此也就没有变量引用Timer对象,所以垃圾收集这时会回收Timer对象。那么为什么在debug模式下却能够运行能,这跟c#编译器的优化方式有关,在release模式下编译器做了相关的优化操作。而在debug模式下,timer对象的生成期是方法的结束,这样做也是为了调试的方便。要不然在调试时,我们执行到Timer timer = new Timer()后想看timer的值时,已经被垃圾回收器给回收了,这是我们不期望看到的结果,编译器如何处理的,我们可以看看编译器在release模式下和debug模式下对上面的代码编译后生成的IL对比我们既知结果.

release模式编译生成的IL:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.method private hidebysig static void Main( string [] args) cil managed
{
  .entrypoint
  // Code size    32 (0x20)
  .maxstack 8
  IL_0000: ldnull
  IL_0001: ldftn   void GCTest.Program::TimerCallback( object )
  IL_0007: newobj   instance void [mscorlib]System.Threading.TimerCallback::.ctor( object ,
                                            native int )
  IL_000c: ldnull
  IL_000d: ldc.i4.0
  IL_000e: ldc.i4   0x7d0
  IL_0013: newobj   instance void [mscorlib]System.Threading.Timer::.ctor( class [mscorlib]System.Threading.TimerCallback,
                                        object ,
                                        int32,
                                        int32)
  IL_0018: pop
  IL_0019: call    string [mscorlib]System.Console::ReadLine()
  IL_001e: pop
  IL_001f: ret
} // end of method Program::Main

debug模式下生成的IL

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
method private hidebysig static void Main( string [] args) cil managed
{
  .entrypoint
  // Code size    33 (0x21)
  .maxstack 4
  .locals init ([0] class [mscorlib]System.Threading.Timer timer)
  IL_0000: nop
  IL_0001: ldnull
  IL_0002: ldftn   void GCTest.Program::TimerCallback( object )
  IL_0008: newobj   instance void [mscorlib]System.Threading.TimerCallback::.ctor( object ,
                                            native int )
  IL_000d: ldnull
  IL_000e: ldc.i4.0
  IL_000f: ldc.i4   0x7d0
  IL_0014: newobj   instance void [mscorlib]System.Threading.Timer::.ctor( class [mscorlib]System.Threading.TimerCallback,
                                        object ,
                                        int32,
                                        int32)
  IL_0019: stloc.0
  IL_001a: call    string [mscorlib]System.Console::ReadLine()
  IL_001f: pop
  IL_0020: ret
} // end of method Program::Main

从生成的IL中我们可以看出在debug模式下,生成IL比在release模式下多了19行红色字体的IL指令码,该指令码的作用是将15行生成的引用Timer对象的栈上的变量存放到局部变量0中。所以使得在debug模式下该t还被引用,不能够回收Timer对象,所以也能出现我们期盼的结果,那么如何在两种模式下都能得到我们期盼的结果呢。我们可以如下操作.

正确的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Program
   {
     static void Main( string [] args)
     {
       Timer timer = new Timer(TimerCallback, null ,0,2000);
    
       Console.ReadLine();
       timer.Dispose();
     }
 
     private static void TimerCallback( object o)
     {
       Console.WriteLine( "in TimerCallback method" );
 
       GC.Collect();
 
      
     }
   }

这时不管是在release模式下还是debug模式下,都会每隔2秒钟调用我们的回调方法.

最后此篇关于详解C#中的定时器Timer类及其垃圾回收机制的文章就讲到这里了,如果你想了解更多关于详解C#中的定时器Timer类及其垃圾回收机制的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com