j'ai écrit une application multithread pour .NET et dans une partie très importante de code que je donne les résultats suivants:Problèmes de synchronisation: tout semble correct, mais
public class ContainerClass {
private object list_lock;
private ArrayList list;
private object init_lock = new object();
private ThreadClass thread;
public void Start() {
lock(init_lock) {
if (thread == null) {
thread = new ThreadClass();
...
}
}
}
public void Stop() {
lock(init_lock) {
if (thread != null) {
thread.processList(0);
thread.finish();
thread.waitUntilFinished();
thread = null;
} else {
throw new ApplicationException("Assertion failed - already stopped.");
}
...
}
}
private class ThreadedClass {
private ContainerClass container;
private Thread thread;
private bool finished;
private bool actually_finished;
public ThreadedClass(ContainerClass container) {
this.container = container;
thread = new Thread(run);
thread.IsBackground = true;
thread.Start();
}
private void run() {
bool local_finished = false;
while (!local_finished) {
ArrayList to_process = null;
lock (container.list_lock) {
if (container.list.Count > 0) {
to_process = new ArrayList();
to_process.AddRange(container.list);
}
}
if (to_process == null) {
// Nothing to process so wait
lock (this) {
if (!finished) {
try {
Monitor.Wait(this);
} catch (ThreadInterruptedException) {
}
}
}
} else if (to_process.Count > 0) {
// Something to process, so go ahead and process the journals,
int sz = to_process.Count;
// For all elements
for (int i = 0; i < sz; ++i) {
// Pick the lowest element to process
object obj = to_process[i];
try {
// process the element...
...
} catch (IOException e) {
...
// If there is an error processing the best thing to do is finish
lock (this) {
finished = true;
}
}
}
}
lock (this) {
local_finished = finished;
// Remove the elements that we have just processed.
if (to_process != null) {
lock (container.list_lock) {
int sz = to_process.Count;
for (int i = 0; i < sz; ++i) {
container.list.RemoveAt(0);
}
}
}
// Notify any threads waiting
Monitor.PulseAll(this);
}
}
lock (this) {
actually_finished = true;
Monitor.PulseAll(this);
}
}
public void waitUntilFinished() {
lock (this) {
try {
while (!actually_finished) {
Monitor.Wait(this);
}
} catch (ThreadInterruptedException e) {
throw new ApplicationException("Interrupted: " + e.Message);
}
}
}
public void processList(int until_size) {
lock (this) {
Monitor.PulseAll(this);
int sz;
lock (container.list_lock) {
sz = container.list.Count;
}
// Wait until the sz is smaller than 'until_size'
while (sz > until_size) {
try {
Monitor.Wait(this);
} catch (ThreadInterruptedException) {
}
lock (container.list_lock) {
sz = container.list.Count;
}
}
}
}
}
}
Comme vous pouvez le voir, le thread jusqu'à ce que la collection est vide mais il semble que les conflits de synchronisation interdisent au thread d'entrer au point (le seul dans le code entier) où un élément est retiré de la collection list
dans le ContainerClass
. Ce choc provoque le code pour ne jamais revenir et l'application de continuer à fonctionner si la méthode processList
est appelée avec la valeur de until_size
de 0.
Je vous demande mieux développeur que moi (et je pense qu'il ya beaucoup là-bas) pour m'aider à corriger ce petit morceau de code, car je ne comprends vraiment pas pourquoi la liste n'est pas décrémentée ...
Merci beaucoup du fond du coeur.
PS. Je voudrais souligner que le code fonctionne parfaitement pour tout le temps: la seule situation dans laquelle il freine c'est en appelant thread.processList(0)
de ContainerClass.Stop()
.
Pourquoi ce wiki communautaire? – scottm
parce que je ne sais pas ce que «wiki communautaire» signifie dans StackOverflow et je pensais que c'était un moyen de recevoir plus de visibilité ...: P – Antonello
Vous ne recevez pas de points de rep pour répondre. Découvrez la faq en haut de la page. – scottm