C#中Timer使用及解决重入问题

转载 2015年07月07日 15:07:34



解决方案三个,成功解决timer组件和progressbar更新偶尔死机的问题

1、使用lock(Object)的方法来防止重入,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就等待执行,适用重入很少出现的场景(具体也没研究过,可能比较占内存吧)。

 

代码跟上面差不多,在触发的方法中加入lock,这样当线程2进入触发的方法中,发现已经被锁,会等待锁中的代码处理完在执行,代码如下:

1
2
3
4
5
6
7
8
private static object locko = new object(); 
 /// <summary>
 /// System.Timers.Timer的回调方法
 /// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private static void TimersTimerHandler(object sender, EventArgs args)
{
1
int t = ++num; <br>        lock (locko)
1
2
3
4
5
6
7
<em id="__mceDel">        {
            Console.WriteLine(string.Format("线程{0}输出:{1},       输出时间:{2}", t, outPut.ToString(), DateTime.Now));
            System.Threading.Thread.Sleep(2000);
            outPut++;
            Console.WriteLine(string.Format("线程{0}自增1后输出:{1},输出时间:{2}", t, outPut.ToString(), DateTime.Now));
        }
    }</em>

2、设置一个标志,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就放弃(注意这里是放弃,而不是等待哦,看看执行结果就明白啥意思了)执行,适用重入经常出现的场景。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static int inTimer = 0;
/// <summary>
/// System.Timers.Timer的回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private static void TimersTimerHandler(object sender, EventArgs args)
{
    int t = ++num;
    if (inTimer == 0)
    {
        inTimer = 1;
        Console.WriteLine(string.Format("线程{0}输出:{1},       输出时间:{2}", t, outPut.ToString(), DateTime.Now));
        System.Threading.Thread.Sleep(2000);
        outPut++;
        Console.WriteLine(string.Format("线程{0}自增1后输出:{1},输出时间:{2}", t, outPut.ToString(), DateTime.Now));
        inTimer = 0;
    }
}

3、在多线程下给inTimer赋值不够安全,Interlocked.Exchange提供了一种轻量级的线程安全的给对象赋值的方法(感觉比较高上大,也是比较推荐的一种方法),执行结果与方法2一样,也是放弃执行。Interlocked.Exchange用法参考这里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static int inTimer = 0;
/// <summary>
/// System.Timers.Timer的回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private static void TimersTimerHandler(object sender, EventArgs args)
{
    int t = ++num;
    if (Interlocked.Exchange(ref inTimer, 1) == 0)
    {
        Console.WriteLine(string.Format("线程{0}输出:{1},       输出时间:{2}", t, outPut.ToString(), DateTime.Now));
        System.Threading.Thread.Sleep(2000);
        outPut++;
        Console.WriteLine(string.Format("线程{0}自增1后输出:{1},输出时间:{2}", t, outPut.ToString(), DateTime.Now));
        Interlocked.Exchange(ref inTimer, 0);
    }
}


【总结】可重入函数

概要可重入函数,顾名思义,就是多次调用,执行的结果是一致的。在单任务或单线程且没有中断的系统中,程序是顺序执行的,就不存在可重入性的问题。 而在多任务或多线程的系统中,多任务可以同时调用同一函数,即...
  • iluzhiyong
  • iluzhiyong
  • 2016年07月03日 20:07
  • 533

多任务系统——可重入函数

可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏。可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失。     可重入函数使用的变...
  • zjc156m
  • zjc156m
  • 2013年03月21日 09:02
  • 516

关于重入锁的理解

package com.joker.test; import java.util.concurrent.locks.ReentrantLock; /**  *可重入锁  *所谓重入锁,指的是以线程为单...
  • u011567806
  • u011567806
  • 2016年10月11日 17:43
  • 2688

浅谈可重入函数与不可重入函数

在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果有一个函数不幸被设计成为这样:那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。这样的函数是不安全的...
  • lianghe_work
  • lianghe_work
  • 2015年08月13日 14:15
  • 2089

多线程多任务断点下载

多线程下载的原理是这样的:通常服务器同时与多个用户连接,用户之间共享带宽。如果N个用户的优先级都相同,那么每个用户连接到该服务器上的实际带宽就是服务器带宽的N分之一。可以想象,如果用户数目较多,则每个...
  • xiangyong_1521
  • xiangyong_1521
  • 2016年05月03日 20:37
  • 601

Linux可重入函数

1、可重入函数     可重入函数指的是可以被中断的函数。也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了...
  • qq_20480611
  • qq_20480611
  • 2015年11月22日 09:39
  • 461

Java多线程/并发10、不可重入锁/自旋锁、可重入锁

锁分为可重入锁和不可重入锁。 可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法A,这个线程在没有释放这把锁的时候,能否再次进入方法A呢? 可重入锁:可以再次进入方法A,就是说...
  • soonfly
  • soonfly
  • 2017年04月28日 16:39
  • 1609

函数的可重入性理解

最近,项目要求可能需要做博通的交换芯片的驱动程序,涉及到多用户同时进行操作,和大量的数据处理,因此在进行代码架构的时候需要进行前期简单的验证设计。考虑到一点就是程序设计的可重入性。经过简单的搜索,在维...
  • wenchao126
  • wenchao126
  • 2013年01月05日 10:23
  • 3594

可重入函数与不可重入函数概念以及编写规范

不可重入怎么改改成可重入函数。一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函...
  • xy010902100449
  • xy010902100449
  • 2015年06月12日 21:32
  • 2013

Java中的锁——重入锁ReentrantLock

ReentrantLock 是一种支持支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,除此之外,该锁还支持获取锁的公平性和非公平性选择。 1  重入的实现 对于锁的重入,我们来想这样一...
  • u010723709
  • u010723709
  • 2015年12月20日 14:48
  • 2446
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#中Timer使用及解决重入问题
举报原因:
原因补充:

(最多只允许输入30个字)