I'm trying to 开发者_如何学Pythonlock an object whiel itterating through its elements. The arraylist allThreads of mine is really not locked, because during the execution of the "foreach" I get a exception saying "Collection was modified; enumeration operation may not execute." I thought that was the whole deal with lock?
lock (mApp.allThreads)
{
foreach (Thread t in mApp.allThreads)
if (t.Name == "OpcDAWriter" && t != Thread.CurrentThread)
t.Join();
}
I think you might have misunderstood what lock
does for you. It does not prevent other code from manipulating the object that you have taken a lock on. What it does is to prevent one thread from acquiring a long on one object, while another thread is holding the lock.
If you want to prevent one thread from manipulating the collection while another thread is iterating over it, you will need to put both the iterating code, and the manipulating code within lock
blocks, locking on the same object.
Simple sample:
class LockDemo
{
private IList<string> _items;
private object _lock = new object();
public LockDemo()
{
_items = new List<string>(new[] { "one", "two", "three" });
}
public void RemoveItem(string item)
{
lock (_lock)
{
_items.Remove(item);
}
}
public void DoSomethingThatIteratesOverTheList()
{
lock (_lock)
{
foreach (var item in _items)
{
// do something with item
}
}
}
}
Notice how all access to the list (except for the constructor in this case) are wrapped in lock
blocks that are all locking on the same object. Also note that this object is not the list itself, but an object that is used only for locking purposes. This shows that lock
does not lock the object as such, but provides a mechanism to control what parts of the code that may or may not be executed in parallel by different threads.
You are joining into the t
thread, so it probably gets removed from mApp.allThreads
or something else happens due to the join, thus modifying the collection.
Also, just because you are looking the object, not all other methods could lock on it, the lock only works when all methods accesing the object are locking on it. You could try using an external object as your lock parameter, ie:
private readonly _lock = new object();
[...]
lock(_lock)
{
foreach....
}
but I doubt that will change anything.
精彩评论