C#:监控 - 等待,脉搏,PulseAll [英] C# : Monitor - Wait,Pulse,PulseAll
问题描述
我有理解等待()很难
,脉冲()
, PulseAll()
。将所有的人都避免死锁?我想AP preciate如果你解释如何使用他们?
I am having hard time in understanding Wait()
, Pulse()
, PulseAll()
. Will all of them avoid deadlock? I would appreciate if you explain how to use them?
推荐答案
短版:
lock(obj) {...}
短手为 Monitor.Enter
/ Monitor.Exit
(有异常处理等)。如果没有其他人有锁,你可以得到它(并运行code) - 否则你的线程被阻塞,直到锁被获得性(由另一个线程释放它)
is short-hand for Monitor.Enter
/ Monitor.Exit
(with exception handling etc). If nobody else has the lock, you can get it (and run your code) - otherwise your thread is blocked until the lock is aquired (by another thread releasing it).
死锁通常发生在两种答:两个线程以不同的顺序锁定的东西:
Deadlock typically happens when either A: two threads lock things in different orders:
thread 1: lock(objA) { lock (objB) { ... } }
thread 2: lock(objB) { lock (objA) { ... } }
(在这里,如果他们每个人获得的第一个锁,也不能的曾经的拿到第二,因为没有线程可以退出来释放自己的锁)
(here, if they each acquire the first lock, neither can ever get the second, since neither thread can exit to release their lock)
此情况,可以通过以相同的顺序始终锁定被最小化;你可以使用恢复(在一定程度上) Monitor.TryEnter
(而不是 Monitor.Enter
/ 锁定
),并指定超时。
This scenario can be minimised by always locking in the same order; and you can recover (to a degree) by using Monitor.TryEnter
(instead of Monitor.Enter
/lock
) and specifying a timeout.
或B:您可以阻止自己的东西一样的WinForms当线程切换,同时保持一个锁:
or B: you can block yourself with things like winforms when thread-switching while holding a lock:
lock(obj) { // on worker
this.Invoke((MethodInvoker) delegate { // switch to UI
lock(obj) { // oopsiee!
...
}
});
}
僵局出现明显之上,但是当你有面条code也不是那么明显;可能的答案:不线程开关,同时持有锁,或使用的BeginInvoke
,这样你至少可以退出锁(让UI播放)
The deadlock appears obvious above, but it isn't so obvious when you have spaghetti code; possible answers: don't thread-switch while holding locks, or use BeginInvoke
so that you can at least exit the lock (letting the UI play).
等待
/ 脉冲
/ PulseAll
是不同的;它们是用于信令。我用这个在这个答案信号,因此:
Wait
/Pulse
/PulseAll
are different; they are for signalling. I use this in this answer to signal so that:
-
出列
:如果您尝试在队列为空出列数据,它等待另一个线程来添加数据,这会唤醒阻塞的线程 -
排队
:如果你试图排队数据时队列已满,它等待另一个线程删除数据,这唤醒阻塞的线程
Dequeue
: if you try to dequeue data when the queue is empty, it waits for another thread to add data, which wakes up the blocked threadEnqueue
: if you try and enqueue data when the queue is full, it waits for another thread to remove data, which wakes up the blocked thread
脉冲
只醒来的有一个的话题 - 但我不是足够聪明来证明下一个线程始终是一个我想要的,所以我倾向于使用 PulseAll
,并简单地重新验证,然后再继续的条件;作为一个例子:
Pulse
only wakes up one thread - but I'm not brainy enough to prove that the next thread is always the one I want, so I tend to use PulseAll
, and simply re-verify the conditions before continuing; as an example:
while (queue.Count >= maxSize)
{
Monitor.Wait(queue);
}
通过这种方法,我可以放心地加入脉冲
,其他的含义没有我的存在code假设我醒过来,因此没有数据 - 这为方便的时候(在相同的例子),我以后需要添加一个关闭()
方法。
With this approach, I can safely add other meanings of Pulse
, without my existing code assuming that "I woke up, therefore there is data" - which is handy when (in the same example) I later needed to add a Close()
method.
这篇关于C#:监控 - 等待,脉搏,PulseAll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!