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



解决方案三个,成功解决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);
     }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值