Per risolvere questa situazione ci possono essere davvero molti molti prototipi, tuttavia ogni programmatore ha diritto di scegliere che cosa utilizzare.
Il problema di fondo e che accedere in modo concorrenziale a chi dovrà contenere
i dati potrebbe generalmente essere causa di sovrascritture .. o affini.
In questo esempio utilizzo il Mutex, anche se onestamente ritengo molto più edificante utilizzare il lock.
L'esempio pratico.
public class simpleEntity
{
#region Private Properties
private int _id_simpleEntity = 0;
private string _CreationDate ="";
private string _ThreadOwner ="";
#endregion
#region Public Properties
public int id_simpleEntity
{
get { return _id_simpleEntity; }
set { _id_simpleEntity = value; }
}
public string CreationDate
{
get { return _CreationDate; }
set { _CreationDate = value; }
}
public string ThreadOwner
{
get { return _ThreadOwner; }
set { _ThreadOwner = value; }
}
#endregion
}
La mia "solita entity"..
public class simpleEntityList:List<simpleEntity>
{
Mutex _mtx = new Mutex();
public void AddEntity(simpleEntity se)
{
_mtx.WaitOne();
this.Add(se);
_mtx.ReleaseMutex();
}
public void RemoveEntity(int idx)
{
_mtx.WaitOne();
this.RemoveAt(idx);
_mtx.ReleaseMutex();
}
public int CountEntity()
{
int j = 0;
_mtx.WaitOne();
j = this.Count;
_mtx.ReleaseMutex();
return j;
}
}
Questa è la collection, che tuttavia non è proprio la solita.
Non è difficile notare la presenza del Mutex sugli metodi principali.
public class _threadParameters
{
public int _maxEntity;
public string _owner;
public simpleEntityList _sel;
}
Il mio state object.
public class simpleEntityCreator
{
Mutex _mtx = new Mutex();
public void buildEntity(object lthp)
{
_threadParameters thp = (_threadParameters)lthp;
int startID = Program._sx.CountEntity() +1;
for (int i = 0; i < thp._maxEntity; i++)
{
simpleEntity se = new simpleEntity();
se.id_simpleEntity = startID + i;
se.ThreadOwner = thp._owner;
se.CreationDate = DateTime.Now.ToLongTimeString();
//Program._sx.AddEntity(se);
thp._sel.AddEntity(se);
}
_mtx.WaitOne();
Console.WriteLine("***********************************************");
Console.WriteLine(thp._owner +" ha finito ");
for (int i = 0; i < Program._sx.Count; i++)
{
if (Program._sx[i].ThreadOwner == thp._owner)
Console.WriteLine(" id : " + Program._sx[i].id_simpleEntity.ToString() + "|" +
Program._sx[i].ThreadOwner.ToString() + "|" + Program._sx[i].CreationDate);
}
Console.WriteLine("***********************************************");
_mtx.ReleaseMutex();
}
}
Questa classe si preoccupa di Riempire la lista... e di scrivere che cosa sta
combinando ( come se fosse un Trace... )
class Program
{
public static simpleEntityList _sx = new simpleEntityList();
static void Main(string[] args)
{
Console.WriteLine("Main Start");
Console.ReadLine();
_threadParameters tph1 = new _threadParameters();
_threadParameters tph2 = new _threadParameters();
tph1._sel = _sx;
tph2._sel = _sx;
simpleEntityCreator _sec = new simpleEntityCreator();
Thread tFiller1 = new Thread(
new ParameterizedThreadStart(_sec.buildEntity));
tph1._maxEntity = 20;
tph1._owner = "t1";
tFiller1.Start(tph1);
Thread tFiller2 = new Thread(
new ParameterizedThreadStart(_sec.buildEntity));
tph2._maxEntity = 35;
tph2._owner = "t2";
tFiller2.Start(tph2);
Console.WriteLine("Main End");
Console.ReadLine();
}
}
E questo è il main ....
Per comprendere bene che cosa avvine l'unica è provarlo... anche se in debug, non è sempre comprensibile ( dato che si tratta di due thread distinti ) quale è in azione.
Nessun commento:
Posta un commento