System.Timers.Timer是否在与创建它的线程不同的线程上运行?
可以说我有一个带有计时器的类,该计时器每5秒触发一次。当计时器触发时,在经过的方法中,某些对象被修改。可以说,修改该对象需要很长时间,例如10秒。在这种情况下,是否可能会遇到线程冲突?
Answers:
这取决于。将System.Timers.Timer有两种操作模式。  
如果SynchronizingObject将设置为ISynchronizeInvoke实例,则Elapsed事件将在托管同步对象的线程上执行。通常这些ISynchronizeInvoke实例是没有比普通的老式其他Control和Form情况下,我们都熟悉。因此,在那种情况下,Elapsed事件是在UI线程上调用的,其行为类似于System.Windows.Forms.Timer。否则,它实际上取决于所使用的特定ISynchronizeInvoke实例。
如果SynchronizingObject为null,则在线程Elapsed上调用该事件ThreadPool,其行为类似于System.Threading.Timer。实际上,它实际上在System.Threading.Timer后台使用了一个幕后,并在收到计时器回调(如果需要)之后进行编组操作。
System.Threading.Timeror还是System.Timers.Timer?
                    System.Timers.Timer都有两种操作模式。它可以在随机分配的线程池线程上运行,也可以在托管ISynchronizeInvoke实例的任何线程上运行。我不知道该如何澄清。System.Threading.Timer与原始问题关系不大(如果有的话)。
                    lock吗?
                    除非先前的“经过”仍在运行,否则每个经过的事件都将在同一线程中触发。
因此它为您处理了碰撞
尝试将其放在控制台中
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秒钟进行编辑,则需要进行一些锁定才能跳过某些编辑。
timer.Stop()在Elapsed事件方法的开头添加a ,然后在Elapsed事件方法timer.Start()的末尾添加a 可以防止Elapsed事件发生冲突。
                    对于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是在Workers线程上执行的。
不,进一步的复杂化-如果您将间隔缩短为10毫秒,
Main Thread Id: 9
   11
   13
   12
   22
   17
   ... 这是因为,如果在触发下一个刻度时未完成OnDummyTimerFired的先前执行,则.NET将创建一个新线程来执行此工作。
更复杂的是,“ System.Timers.Timer类提供了一种解决此难题的简便方法,它公开了一个公共的SynchronizingObject属性。将该属性设置为Windows Form实例(或Windows Form上的控件)将确保您的Elapsed事件处理程序中的代码将在实例化SynchronizingObject的同一线程上运行。”
如果经过的事件花费的时间比间隔时间长,它将创建另一个线程来引发经过的事件。但是有一个解决方法
static void timer_Elapsed(object sender, ElapsedEventArgs e)    
{     
   try
   {
      timer.Stop(); 
      Thread.Sleep(2000);        
      Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);    
   }
   finally
   {
     timer.Start();
   }
}