定时器与锁

8.1定时器

若要长期定时进行一些工作,比如像邮箱更新,实时收听信息等等,可以利用定时器Timer进行操作。
在System.Threading命名空间中存在Timer类与对应的TimerCallback委托,它可以在后台线程中执行一些长期的定时操作,使主线程不受干扰。
Timer类中最常用的构造函数为 public Timer( timerCallback , object , int , int )
timerCallback委托可以绑定执行方法,执行方法必须返回void,它可以是无参数方法,也可以带一个object参数的方法。
第二个参数是为 timerCallback 委托输入的参数对象。
第三个参数是开始执行前等待的时间。
第四个参数是每次执行之间的等待时间。

开发实例

复制代码
 1     class Program
2 {
3 static void Main(string[] args)
4 {
5 ThreadPool.SetMaxThreads(1000, 1000);
6
7 TimerCallback callback = new TimerCallback(ThreadPoolMessage);
8 Timer t = new Timer(callback,"Hello Jack! ", 0, 1000);
9 Console.ReadKey();
10 }
11
12 //显示线程池现状
13 static void ThreadPoolMessage(object data)
14 {
15 int a, b;
16 ThreadPool.GetAvailableThreads(out a, out b);
17 string message = string.Format("{0}\n CurrentThreadId is:{1}\n" +
18 " CurrentThread IsBackground:{2}\n" +
19 " WorkerThreads is:{3}\n CompletionPortThreads is:{4}\n",
20 data + "Time now is " + DateTime.Now.ToLongTimeString(),
21 Thread.CurrentThread.ManagedThreadId,
22 Thread.CurrentThread.IsBackground.ToString(),
23 a.ToString(), b.ToString());
24 Console.WriteLine(message);
25 }
26 }
复制代码

注意观察运行结果,每次调用Timer绑定的方法时不一定是使用同一线程,但线程都会是来自工作者线程的后台线程。


8.2 锁

在使用多线程开发时,存在一定的共用数据,为了避免多线程同时操作同一数据,.NET提供了lock、Monitor、Interlocked等多个锁定数据的方式。

8.2.1 lock

lock的使用比较简单,如果需要锁定某个对象时,可以直接使用lock(this)的方式。

复制代码
1 private void Method()
2 {
3 lock(this)
4 {
5 //在此进行的操作能保证在同一时间内只有一个线程对此对象操作
6 }
7 }
复制代码

如果操作只锁定某段代码,可以事先建立一个object对象,并对此对象进行操作锁定,这也是.net提倡的锁定用法。

复制代码
 1 class Control
2 {
3 private object obj=new object();
4
5 public void Method()
6 {
7 lock(obj)
8 {.......}
9 }
10 }
复制代码

8.2.2 Montior

Montior存在于System.Thread命名空间内,相比lock,Montior使用更灵活。
它存在 Enter, Exit 两个方法,它可以对对象进行锁定与解锁,比lock使用更灵活。

复制代码
 1 class Control
2 {
3 private object obj=new object();
4
5 public void Method()
6 {
7 Monitor.Enter(obj);
8 try
9 {......}
10 catch(Excetion ex)
11 {......}
12 finally
13 {
14 Monitor.Exit(obj);
15 }
16 }
17 }
18
复制代码

使用try的方式,能确保程序不会因死锁而释放出异常!
而且在finally中释放obj对象能够确保无论是否出现死锁状态,系统都会释放obj对象。
而且Monitor中还存在Wait方法可以让线程等待一段时间,然后在完成时使用Pulse、PulseAll等方法通知等待线程。

8.2.3 Interlocked

Interlocked存在于System.Thread命名空间内,它的操作比Monitor使用更简单。
它存在CompareExchange、Decrement、Exchange、Increment等常用方法让参数在安全的情况进行数据交换。

Increment、Decrement 可以使参数安全地加1或减1并返回递增后的新值。

复制代码
1 class Example
2 {
3 private int a=1;
4
5 public void AddOne()
6 {
7 int newA=Interlocked.Increment(ref a);
8 }
9 }
复制代码

Exchange可以安全地变量赋值。

1 public void SetData()
2 {
3 Interlocked.Exchange(ref a,100);
4 }

CompareExchange使用特别方便,它相当于if的用法,当a等于1时,则把100赋值给a。

1 public void CompareAndExchange()
2 {
3 Interlocked.CompareExchange(ref a,100,1);
4 }
原文地址:https://www.cnblogs.com/meilibao/p/2725748.html