关闭

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

297人阅读 评论(0) 收藏 举报
分类:



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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:8666次
    • 积分:199
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:19篇
    • 译文:0篇
    • 评论:0条
    文章分类