I realise that my post was incomplete - I didn't address the SyncRoot issue. Take the following code:
static void Main(string[] args)
{
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
Thread t = new Thread(new ThreadStart(Ouch));
t.Start();
lock(arr.SyncRoot)
{
foreach(object o in arr)
{
Thread.Sleep(1000);
o.ToString();
}
}
}
static void Ouch()
{
Thread.Sleep(1000);
arr.RemoveAt(0);
}
This throws an InvalidOperationException because the collection was modified during iteration by the Ouch method running on the other thread. In other words, the SyncRoot is useless on its own in the default case. However, add the following line of code just before the creation of the Thread object (or at least before the thread is started).
arr = ArrayList.Synchronized(arr);
This creates a thread safe wrapper around the arraylist with operations locking the SyncRoot internally. Now the code will perform correctly as the foreach is synchronized with the modifications.
Regards
Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog
nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<e3*************@TK2MSFTNGP15.phx.gbl>
I have to say that I think lock to be maybe the worst named keyword in the language. It gives the impression that it imposes some kind of invisible force field around the object in question that cannot be pierced by other code until the code block executes. This unfortunately is rubbish.
lock(obj)
{
// some thread sensitive code here
}
translates to
Monitor.Enter(obj);
try
{
// some thread sensitive code here
}
finally
{
Monitor.Exit(obj);
}
and all Monitor.Enter (simplistically) does is manipulate the SyncBlock in the objects header. Conceptually It stamps its thread id against the SyncBlock. If another thread id is already stamped there it blocks until the SyncBlock becomes "un-owned" then proceeds to stamp its thread id against the SyncBlock. Monitor.Exit clears the threads id from the syncblock.
So simply stating lock() on anything at all (even if it is the SyncRoot) will achieve nothing UNLESS all code that is accessing the rescource ALSO calls lock on the same thing. In other words
lock(obj)
{
// access some shared. thread sensitive resource
}
only guarantees thread synchronization if all code calls lock(obj), obj being the same physical object as above, before accessing the shared resource.
With collections you can create a thread safe wrapper wound the collection using the Synchronized method - but all this does is do the appropriate locking internally.
One final thing about lock. lock is a block with no timeout. If you get a thread deadlock your application is hosed. The Monitor class also has a TryEnter method which you can pass a timeout to. Ian Griffiths has written a nice wrapper for this which allows you to use stcks based release using the "using" keyword. Heres the URL
http://www.interact-sw.co.uk/iangblo.../03/23/locking
Regards
Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog
nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<ug*************@tk2msftngp13.phx.gbl>
Nop... I owe you an apology. I wrote Syncronized instead of SyncRoot :$
I meant something like this...
ArrayList al = new ArrayList();
lock(al.SyncRoot) {
foreach(object item in al) {
// Enumerate
}
}
Regards
"Sharon" <sh****@void.null> escribi? en el mensaje
news:Om**************@TK2MSFTNGP09.phx.gbl...
Should i try it this way:
lock(ArrayList.Synchronized(arrayListInstance))
{
enumerate...
}
And not this way:
lock(arrayListInstance)
{
enumerate...
}
"Angel J. Hern?ndez" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...
Are you locking the ArrayList or ArrayList.Syncronized property?
Regards,
--
Angel J. Hern?ndez M.
MCSD
"Sharon" <sh****@void.null> escribi? en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl... > Hi all.
> I have an ArrayList and
> sometimes while enumerating through, i get an
> exception because another thread has added to the ArrayList.
> To solve this problem, i lock the enumeration,
> passing the ArrayList instance to the lock.
> But i still get the same exception.
> Thanks for your help.
> Sharon.
>
>
---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com).
Version: 6.0.770 / Virus Database: 517 - Release Date: 27/09/2004
[microsoft.public.dotnet.languages.csharp]
---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com).
Version: 6.0.770 / Virus Database: 517 - Release Date: 27/09/2004
[microsoft.public.dotnet.languages.csharp]