• 定时器与锁


    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 }
  • 相关阅读:
    JS 百度地图路书---动态路线
    jQuery---创建和添加节点
    CSS基础
    第一篇:前端知识之HTML内容
    JS高级---为内置对象添加原型方法
    JS DOM属性+JS事件
    Vue-router
    vue使用kkfileview文件预览功能
    JS高级---案例:验证密码的强度
    promise是怎么来的?
  • 原文地址:https://www.cnblogs.com/meilibao/p/2725748.html
Copyright © 2020-2023  润新知