同步异常
我有两个线程,一个线程处理队列,另一个线程将内容添加到队列中。
- 我想在队列处理线程完成处理队列后将其置于睡眠状态
- 我想让第二个线程告诉它在向队列添加项目时唤醒
但是这些函数调用 System.Threading.SynchronizationLockException:对象同步方法是从 Monitor.PulseAll(waiting);
调用上的未同步代码块 调用的,因为我尚未将该函数与等待对象同步。 [我不想这样做,我希望能够在将项目添加到队列时进行处理]。我怎样才能实现这个目标?
Queue<object> items = new Queue<object>();
object waiting = new object();
第一个线程
public void ProcessQueue()
{
while (true)
{
if (items.Count == 0)
Monitor.Wait(waiting);
object real = null;
lock(items) {
object item = items.Dequeue();
real = item;
}
if(real == null)
continue;
.. bla bla bla
}
}
第二个线程涉及
public void AddItem(object o)
{
... bla bla bla
lock(items)
{
items.Enqueue(o);
}
Monitor.PulseAll(waiting);
}
I have two threads, one thread processes a queue and the other thread adds stuff into the queue.
- I want to put the queue processing thread to sleep when its finished processing the queue
- I want to have the 2nd thread tell it to wake up when it has added an item to the queue
However these functions call System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code
on the Monitor.PulseAll(waiting);
call, because I havent synchronized the function with the waiting object. [which I dont want to do, i want to be able to process while adding items to the queue]. How can I achieve this?
Queue<object> items = new Queue<object>();
object waiting = new object();
1st Thread
public void ProcessQueue()
{
while (true)
{
if (items.Count == 0)
Monitor.Wait(waiting);
object real = null;
lock(items) {
object item = items.Dequeue();
real = item;
}
if(real == null)
continue;
.. bla bla bla
}
}
2nd Thread involves
public void AddItem(object o)
{
... bla bla bla
lock(items)
{
items.Enqueue(o);
}
Monitor.PulseAll(waiting);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用信号量 http://msdn.microsoft.com/library/system.threading.semaphore .aspx 正是为此而设计的
Use Semaphore http://msdn.microsoft.com/library/system.threading.semaphore.aspx it was designed exactly for this
答案在您发布的错误消息中:
“从 Monitor.PulseAll(waiting) 上的未同步代码块调用对象同步方法;”
您必须从lock(waiting)块内部调用Monitor.PulseAll(waiting)。
另外...您还必须从锁块内调用 Monitor.Wait 。
The answer is in the error message you posted:
"Object synchronization method was called from an unsynchronized block of code on the Monitor.PulseAll(waiting);"
You have to call Monitor.PulseAll(waiting) from inside the lock(waiting) block.
Also... you have to call Monitor.Wait from within a lock block as well.
如果您可以访问.NET 4.0,则可以通过来实现您想要做的事情BlockingCollection 。
如果您想通过
Monitor
类自己完成此操作并使用Pulse()
发出信号,那么您实际上走在正确的轨道上。您会收到异常,因为调用
Wait()
、Pulse()
和PulseAll()
、您必须拥有指定对象的锁
。您恰好在等待
时错过了这个。可以使用的示例基本线程安全队列:
foreach
,while
或您最喜欢的条件构造,lock()
、Monitor.Pulse()
、Monitor.PulseAll()
和Monitor.Wait()
:。
使用示例:
If you have access to .NET 4.0, what you want to do can be achieved by BlockingCollection<T>.
If you want to do it yourself by means of the
Monitor
class and signaling withPulse()
, you are actually on the right track.You get the exception because to call
Wait()
,Pulse()
andPulseAll()
, you have to own thelock
on the specified object. You happen to miss this onwaiting
.A sample basic thread-safe queue that can be used:
foreach
on the consumer,while
or your favorite conditional construct on the producer side,lock()
,Monitor.Pulse()
,Monitor.PulseAll()
andMonitor.Wait()
:.
Sample usage:
我更喜欢使用回调来启动一个处理线程,该线程会继续运行直到被捕获,并且锁定会导致同时读取器和写入器排队等待:
I prefer to use a callback that launches a processing thread that continues until it's caught up, with locks causing simultaneous readers and writers to wait in line: