use*_*164 86 c# multithreading timer
System.Timers.Timer是否在与创建它的线程不同的线程上经过?
让我们说我有一个定时器,每5秒触发一次.当计时器触发时,在已用方法中,某些对象被修改.让我们说修改这个对象需要很长时间,比如10秒.在这种情况下,我是否可能遇到线程冲突?
Bri*_*eon 181
这取决于.将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幕后操作,并在收到定时器回调后进行编组操作(如果需要).
Jor*_*ren 56
有关定时器的MSDN文档说明:
System.Threading.Timer类在ThreadPool线程上进行回调,根本不使用事件模型.
确实,计时器在不同的线程上流逝.
Sim*_*mon 21
除非先前的Elapsed仍在运行,否则每个已过去的事件将在同一个线程中触发.
所以它为你处理碰撞
尝试把它放在控制台中
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);
}
Run Code Online (Sandbox Code Playgroud)
你会得到这样的东西
10
6
12
6
12
Run Code Online (Sandbox Code Playgroud)
其中10是调用线程,6和12是从bg逝去事件触发.如果删除Thread.Sleep(2000); 你会得到这样的东西
10
6
6
6
6
Run Code Online (Sandbox Code Playgroud)
由于没有碰撞.
但这仍然让你有问题.如果你每5秒触发一次事件并且需要10秒钟来编辑你需要一些锁定来跳过一些编辑.
Swa*_*Jat 15
对于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;
}
Run Code Online (Sandbox Code Playgroud)
如果DummyTimer以5秒的间隔触发,你会看到输出:
Main Thread Id: 9
12
12
12
12
12
...
Run Code Online (Sandbox Code Playgroud)
因此,如图所示,OnDummyTimerFired在Workers线程上执行.
不,进一步复杂化 - 如果你将间隔减少到10毫秒,
Main Thread Id: 9
11
13
12
22
17
...
Run Code Online (Sandbox Code Playgroud)
这是因为如果在下一个tick被触发时没有完成OnDummyTimerFired的上一次执行,那么.NET将创建一个新线程来完成这项工作.
更复杂的是,"System.Timers.Timer类提供了一种处理这种困境的简单方法 - 它公开了一个公共的SynchronizingObject属性.将此属性设置为Windows窗体的实例(或Windows窗体上的控件)将确保您的Elapsed事件处理程序中的代码在实例化SynchronizingObject的同一线程上运行."
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2
小智 12
如果经过的事件比间隔花费的时间长,它将创建另一个线程来提升已经过去的事件.但是有一个解决方法
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
timer.Stop();
Thread.Sleep(2000);
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
finally
{
timer.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
101497 次 |
| 最近记录: |