难道C#定时器经过一个单独的线程?(Do C# Timers elapse on a separat

2019-07-18 07:10发布

做了System.Timers.Timer经过上比创建它的线程一个单独的线程?

可以说,我有一个类与每5秒触发一个计时器。 当计时器触发,在经过的方法,一些对象被修改。 可以说,这需要很长的时间来修改这个对象,比如10秒。 是否有可能,我会在这种情况下碰上线程冲突?

Answer 1:

对于System.Timers.Timer :

请参见下面的布赖恩·基甸的答案

对于System.Threading.Timer :

关于定时器MSDN文档指出:

该System.Threading.Timer类使得在一个线程池线程回调并不会在所有使用的事件模型。

因此,我们确实在定时器结束在不同的线程。



Answer 2:

这取决于。 该System.Timers.Timer有两种操作模式。

如果SynchronizingObject设置为ISynchronizeInvoke实例,然后将Elapsed事件将在托管同步对象的线程上。 通常这些ISynchronizeInvoke情况下是没有比普通的老式其他ControlForm大家都熟悉的例子。 因此,在这种情况下, Elapsed事件调用UI线程上和它的行为类似于System.Windows.Forms.Timer 。 否则,它真的取决于具体ISynchronizeInvoke使用该实例。

如果SynchronizingObject为null,则Elapsed事件上调用一个ThreadPool线程,它的行为类似System.Threading.Timer 。 事实上,它实际上采用的是System.Threading.Timer幕后,如果需要,它接收到的计时器回调之后做编排操作。



Answer 3:

每个经过的事件将触发在同一个线程,除非先前已用仍在运行。

因此,它可以为您处理碰撞

尝试把这个在控制台

static void Main(string[] args)
{
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    var timer = new Timer(1000);
    timer.Elapsed += timer_Elapsed;
    timer.Start();
    Console.ReadLine();
}

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    Thread.Sleep(2000);
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}

你会得到这样的事情

10
6
12
6
12

其中10是调用线程和6和12从BG经过事件触发。 如果删除了Thread.Sleep(2000); 你会得到这样的事情

10
6
6
6
6

由于没有冲突。

但是,这仍然让ü一个问题。 如果u是触发事件每隔5秒,它需要10秒编辑u需要一些锁定跳过一些编辑。



Answer 4:

对于System.Timers.Timer,在单独的线程,如果是对于SynchronizingObject没有设置。

    static System.Timers.Timer DummyTimer = null;

    static void Main(string[] args)
    {
        try
        {

            Console.WriteLine("Main Thread Id: " + System.Threading.Thread.CurrentThread.ManagedThreadId);

            DummyTimer = new System.Timers.Timer(1000 * 5); // 5 sec interval
            DummyTimer.Enabled = true;
            DummyTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnDummyTimerFired);
            DummyTimer.AutoReset = true;

            DummyTimer.Start();

            Console.WriteLine("Hit any key to exit");
            Console.ReadLine();
        }
        catch (Exception Ex)
        {
            Console.WriteLine(Ex.Message);
        }

        return;
    }

    static void OnDummyTimerFired(object Sender, System.Timers.ElapsedEventArgs e)
    {
        Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
        return;
    }

输出你会看到,如果DummyTimer 5秒的间隔发射:

Main Thread Id: 9
   12
   12
   12
   12
   12
   ... 

所以,正如所见,OnDummyTimerFired是在工人线程中执行。

不,更复杂的 - 如果减少间隔说10毫秒,

Main Thread Id: 9
   11
   13
   12
   22
   17
   ... 

这是因为,如果在接下来的蜱被激发不这样做OnDummyTimerFired的分组执行,那么.NET将创建一个新的线程来完成这项工作。

更为复杂的事情,“该System.Timers.Timer类提供了一个简单的方法来解决这一难题,它暴露了一个公共属性SynchronizingObject的。这个属性设置为Windows窗体(或Windows窗体上的控制)的实例将确保在你经过的事件处理程序代码在其上用SynchronizingObject的实例化的同一个线程上运行“。

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2



Answer 5:

另一方面,在经过事件需要更长的时间,然后间隔,它会创建另一个线程来提高所经过的事件。 但对于这个解决方法

static void timer_Elapsed(object sender, ElapsedEventArgs e)    
{     
   try
   {
      timer.Stop(); 
      Thread.Sleep(2000);        
      Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);    
   }
   finally
   {
     timer.Start();
   }
}


文章来源: Do C# Timers elapse on a separate thread?