Can i ask about this for 5369 source

05/13/2011 17:08 marlyandedsel#1
I have this error I dunno what the cause can you tell me what to do please

I have here the image.
05/13/2011 17:13 12tails#2
for god... kill yourself....

if you just read the error you would know the answer....

this mean that you added or removed a value from the collection while doing an operation... for example using the foreach...
05/13/2011 18:31 { Angelius }#3
some extra info on what 12tails just said ,
The problem is that, if you are doing a foreach loop over a collection, and another thread modifies the collection, the enumerator used in foreach is no longer valid. This will cause an exception to throw at that point.

on how to fix it.

you can do something like this .

Quote:
static public Dictionary<T, T2> ThreadSafeDictionary<T, T2>(this Dictionary<T, T2> dictionary)
{
Dictionary<T, T2> copy;
Monitor.Enter(dictionary);
try
{
copy = new Dictionary<T, T2>(dictionary);
}
finally { Monitor.Exit(dictionary); }
return copy;
}
maybe you can use the lock statement to but either way it works but you have to lock the dictionaries while reading/modifying to reach the thread safe point and to avoid such errors

and remember try to keep the lock blocks as small as possible, but make sure they are always locking around the shared resources correctly.

Good Luck .
05/14/2011 04:03 marlyandedsel#4
Quote:
Originally Posted by { Angelius } View Post
some extra info on what 12tails just said ,
The problem is that, if you are doing a foreach loop over a collection, and another thread modifies the collection, the enumerator used in foreach is no longer valid. This will cause an exception to throw at that point.

on how to fix it.

you can do something like this .


maybe you can use the lock statement to but either way it works but you have to lock the dictionaries while reading/modifying to reach the thread safe point and to avoid such errors

and remember try to keep the lock blocks as small as possible, but make sure they are always locking around the shared resources correctly.

Good Luck .


Here is the code i found in that error.....

foreach (Game.Entity monster in Owner.Map.Entities.Values)
{
if (Kernel.GetDistance(monster.X, monster.Y, Owner.Entity.X,
Owner.Entity.Y) <= Constants.nScreenDistance &&
!Contains(monster.UID))
{
if (!monster.Dead)
{
monster.SendSpawn(Owner);
}
}
}


hmmm.. what things to do. yes I get some ideas but, Im sorry for that I just really want to learn on how to do this....
05/14/2011 04:09 { Angelius }#5
Quote:
Originally Posted by marlyandedsel View Post
Here is the code i found in that error.....

foreach (Game.Entity monster in Owner.Map.Entities.Values)
{
if (Kernel.GetDistance(monster.X, monster.Y, Owner.Entity.X,
Owner.Entity.Y) <= Constants.nScreenDistance &&
!Contains(monster.UID))
{
if (!monster.Dead)
{
monster.SendSpawn(Owner);
}
}
}


hmmm.. what things to do. yes I get some ideas but, Im sorry for that I just really want to learn on how to do this....

create a static class and call it Dictionary and copy paste the thread safe dictionary void that i provided in the earlier replay to it ,

so it looks like this

Quote:
static class Dictionary
{
static public Dictionary<T, T2> ThreadSafeDictionary<T, T2>(this Dictionary<T, T2> dictionary)
{
Dictionary<T, T2> copy;
Monitor.Enter(dictionary);
try
{
copy = new Dictionary<T, T2>(dictionary);
}
finally { Monitor.Exit(dictionary); }
return copy;
}
}
and change the void to look like this ,

Quote:
foreach (Game.Entity monster in Dictionary.ThreadSafeDictionary(Owner.Map.Entities ).Values)
{
if (Kernel.GetDistance(monster.X, monster.Y, Owner.Entity.X,
Owner.Entity.Y) <= Constants.nScreenDistance &&
!Contains(monster.UID))
{
if (!monster.Dead)
{
monster.SendSpawn(Owner);
}
}
}
and you'll never get that error again

a small edit for more information about it :

the code snip that i provided up there should lock the original dictionary which is (Owner.Map.Entities) to make sure its protected while copying it creates a new empty dictionary copies the original dictionary(Owner.Map.Entities)key's/value's to the new dictionary and returns the created copy not the original dictionary ,

so when you do the for each you are doing it using the copy not the original which mean if somehow you modify the original dictionary while doing a for each you are not gonna get that error and the original dictionary should be secured all the time by locking it every time you try to read it/modify it .

Good luck
05/14/2011 06:08 marlyandedsel#6
Quote:
Originally Posted by { Angelius } View Post
create a static class and call it Dictionary and copy paste the thread safe dictionary void that i provided in the earlier replay to it ,

so it looks like this


and change the void to look like this ,



and you'll never get that error again

a small edit for more information about it :

the code snip that i provided up there should lock the original dictionary which is (Owner.Map.Entities) to make sure its protected while copying it creates a new empty dictionary copies the original dictionary(Owner.Map.Entities)key's/value's to the new dictionary and returns the created copy not the original dictionary ,

so when you do the for each you are doing it using the copy not the original which mean if somehow you modify the original dictionary while doing a for each you are not gonna get that error and the original dictionary should be secured all the time by locking it every time you try to read it/modify it .

Good luck

I just add like this
Quote:
namespace Conquer_Online_Server.Game
{
//

static class Dictionary
{
static public Dictionary<T, T2> ThreadSafeDictionary<T, T2>(this Dictionary<T, T2> dictionary)
{
Dictionary<T, T2> copy;
Monitor.Enter(dictionary);
try
{
copy = new Dictionary<T, T2>(dictionary);
}
finally { Monitor.Exit(dictionary); }
return copy;
}
}
//
and i just add the code you give and delete the older one like this

Quote:
/* foreach (Game.Entity monster in Owner.Map.Entities.Values)
{
if (Kernel.GetDistance(monster.X, monster.Y, Owner.Entity.X, Owner.Entity.Y) <= Constants.nScreenDistance && !Contains(monster.UID))
{
if (!monster.Dead)
{
monster.SendSpawn(Owner);
}
}
} */
//

foreach (Game.Entity monster in Dictionary.ThreadSafeDictionary(Owner.Map.Entities ).Values)
{
if (Kernel.GetDistance(monster.X, monster.Y, Owner.Entity.X,
Owner.Entity.Y) <= Constants.nScreenDistance &&
!Contains(monster.UID))
{
if (!monster.Dead)
{
monster.SendSpawn(Owner);
}
}
}
//

it working fine... is it correct .... thanks mate your just a nice person here...