[C#]System.Timers.Timer(2)

前端之家收集整理的这篇文章主要介绍了[C#]System.Timers.Timer(2)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

摘要

之前学习过c#中定时器Timer的基本用法,在使用过程中,有一个问题,一直困扰着自己,就是在初始化定时器的时候,如果设置的interval过小,或者每次执行的业务非常耗时的时候,这时候该怎么处理?第一次还没执行结束,下一次已经触发了。

基础

之前学习时的一个例子:

一个例子

如果设置的interval比较大,而业务执行过程耗时很小,如下所示:

<span style="color: #0000ff;">namespace<span style="color: #000000;"> TimerTest
{
<span style="color: #0000ff;">class
<span style="color: #000000;"> Program
{
<span style="color: #0000ff;">static
Timer timer = <span style="color: #0000ff;">new
<span style="color: #000000;"> Timer();
<span style="color: #0000ff;">static
<span style="color: #0000ff;">void
Main(<span style="color: #0000ff;">string<span style="color: #000000;">[] args)
{

        timer.Interval </span>= <span style="color: #800080;"&gt;1000</span><span style="color: #000000;"&gt;;
        timer.AutoReset </span>= <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;;
        timer.Enabled </span>= <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;;
        timer.Elapsed </span>+=<span style="color: #000000;"&gt; timer_Elapsed;
        Console.Read();
    }
    </span><span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;int</span> count = <span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;;
    </span><span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span> timer_Elapsed(<span style="color: #0000ff;"&gt;object</span><span style="color: #000000;"&gt; sender,ElapsedEventArgs e)
    {
        Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;第{0}次触发</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,count.ToString());
        </span><span style="color: #0000ff;"&gt;if</span> (count == <span style="color: #800080;"&gt;10</span><span style="color: #000000;"&gt;)
        {
            timer.Enabled </span>= <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;;
        }
        Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;当前线程:</span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; System.Threading.Thread.CurrentThread.ManagedThreadId);
        System.Threading.Thread.Sleep(</span><span style="color: #800080;"&gt;10</span><span style="color: #000000;"&gt;);
        Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;第{0}次处理完成</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,count.ToString());
        count</span>++<span style="color: #000000;"&gt;;

    }
}

}

执行过程

但实际中由于业务非常复杂,执行很耗时

System.Threading.Thread.Sleep();

可以看到这是,已经开始乱了,线程id已经变了,如果在里面涉及到引用的类型,必然引起多个线程修改同一个变量的问题,造成并不是我们想要的结果。

当然,这个时候有很多处理方法,加锁,或者设置标致量,等本次运行结束时,再运行下一次的。但这种方式,会造成timer的空转。

加锁

<span style="color: #0000ff;">namespace<span style="color: #000000;"> TimerTest
{
<span style="color: #0000ff;">class
<span style="color: #000000;"> Program
{
<span style="color: #0000ff;">static
<span style="color: #0000ff;">readonly
<span style="color: #0000ff;">object
obj = <span style="color: #0000ff;">new
<span style="color: #0000ff;">object
<span style="color: #000000;">();
<span style="color: #0000ff;">static Timer timer = <span style="color: #0000ff;">new<span style="color: #000000;"> Timer();
<span style="color: #0000ff;">static <span style="color: #0000ff;">void Main(<span style="color: #0000ff;">string<span style="color: #000000;">[] args)
{

        timer.Interval </span>= <span style="color: #800080;"&gt;1000</span><span style="color: #000000;"&gt;;
        timer.AutoReset </span>= <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;;
        timer.Enabled </span>= <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;;
        timer.Elapsed </span>+=<span style="color: #000000;"&gt; timer_Elapsed;
        Console.Read();
    }
    </span><span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;int</span> count = <span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;;
    </span><span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span> timer_Elapsed(<span style="color: #0000ff;"&gt;object</span><span style="color: #000000;"&gt; sender,ElapsedEventArgs e)
    {
        </span><span style="color: #0000ff;"&gt;lock</span><span style="color: #000000;"&gt; (obj)
        {
            Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;第{0}次触发</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,count.ToString());
            </span><span style="color: #0000ff;"&gt;if</span> (count == <span style="color: #800080;"&gt;10</span><span style="color: #000000;"&gt;)
            {
                timer.Enabled </span>= <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;;
            }
            Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;当前线程:</span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; System.Threading.Thread.CurrentThread.ManagedThreadId);
            System.Threading.Thread.Sleep(</span><span style="color: #800080;"&gt;2000</span><span style="color: #000000;"&gt;);
            Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;第{0}次处理完成</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,count.ToString());
            count</span>++<span style="color: #000000;"&gt;;
        }

    }
}

}

执行

标志量

timer_Elapsed(= ++= }</span></pre>

运行结果

但仍有另外一种方式,可以在当前处理业务的时候,将当前的timer先停止,执行完毕之后开启。

timer_Elapsed(= (count == = += ++

执行结果

总结

可以尝试测试开启100个定时器甚至更多的进行测试比较,推荐使用处理业务之前关闭,处理结束之后开启的方式。

猜你在找的C#相关文章