I usually have to work with some collections, that are shared among several threads. Because usually these containers represent some logical item of the project domain, it is useful to encapsulate the collection into a seperate class. The following example assumes, that because of speed issues you decide to store the Person references in a Dictionary container. To simplify the work with the container, you encapsulate it into a seperate class:
public class Person
{
private int personId;
public int PersonId
{
get { return personId; }
}
//some other very useful data about the person
//+methods, constructor and so on
}
public delegate void PersonDelegate(Person toAction);
public class PersonsTable
{
private Dictionary
public Person this[int index]
{
get { return thePersons[index]; }
}
public void AddPerson(Person toAdd)
{
thePersons.Add(toAdd.PersonId, toAdd);
OnPersonAdded(toAdd);
}
private void OnPersonAdded(Person wasAdded)
{
if (PersonAdded != null) PersonAdded(wasAdded);
}
public event PersonDelegate PersonAdded;
}
As you see, during the proecting, you decide, that some objects might need to know, that the person was added. You implement it by adding an event object.
Suddenly you realize that you are going to work with this collection from seperate thread, each wanting to get some person`s information. So, you get something like this:
public class PersonsTable
{
private Dictionary
private object syncDictAccess = new object();
public Person this[int index]
{
get
{
lock (syncDictAccess)
{
return thePersons[index];
}
}
}
public void AddPerson(Person toAdd)
{
lock(syncDictAccess)
{
thePersons.Add(toAdd.PersonId, toAdd);
OnPersonAdded(toAdd);
}
}
private void OnPersonAdded(Person wasAdded)
{
if (PersonAdded != null) PersonAdded(wasAdded);
}
public event PersonDelegate PersonAdded;
}
And here we come to the main point: there is a deadlock danger. Raising an event leads to calling external code, that can also ask for the same resourses. It may not even know this. That`s why it is higly recommended never to raise the event or call some external function inside the lock(){} block. Especially events: you never know, what handlers shall use them.