J'ai un service Windows multi-thread assez complexe qui fonctionne, mais je n'arrive pas à comprendre comment nettoyer correctement. Voici un peu de [pseudo] code pour montrer ce que j'ai. Le code actuel est beaucoup plus complexe, probablement trop pour copier/coller ici.Disposer correctement de classe avec thread
Fondamentalement, j'ai une demande de classe qui crée un fil pour faire le travail. Lorsqu'une nouvelle requête arrive dans l'écouteur, elle l'envoie au processeur, ce qui crée la nouvelle demande et maintient la liste des demandes. Si le service est arrêté, je nettoie toutes les demandes de la liste. Mais quand le travail de demande est fait, comment puis-je nettoyer cette instance de la classe?
Merci pour toute aide!
Nelson
class Service
{
Listener listener;
Processor processor;
OnStart()
{
processor = new Processor();
listener = new Listener(processor);
}
OnStop()
{
listener.Dispose();
processor.Dispose();
}
}
class Listener
{
Thread thread;
bool terminate = false;
Listener(Processor processor)
{
thread = new Thread(DoWork);
thread.Start(processor);
}
DoWork(Processor processor)
{
WaitForConnection(NewConnection);
}
NewConnection(String data)
{
processor.NewRequest(data);
if (terminate)
return;
WaitForConnection(NewConnection);
}
Dispose()
{
terminate = true;
thread.Join();
}
}
class Processor
{
//I need to maintain this list so that when the service stops I can cleanly close down
List<Request> requests = new List<Request>();
NewRequest(string data)
{
request.Add(new Request(data));
}
Dispose()
{
//Cleanup each request
foreach (Request request in requests)
{
request.Dispose();
}
}
}
class Request
{
Thread thread;
bool terminate;
Request(string data)
{
while (true)
{
//Do some work
Thread.Sleep(1000);
if (doneWorking)
break;
if (terminate)
return;
}
//We're done. If I return this thread stops. But how do I properly remove this Request instance from the Processor.requests list?
}
Dispose()
{
terminate = true;
thread.Join();
}
}
C'est essentiellement ce que j'ai maintenant. Merci de confirmer. Pourquoi faites-vous des requêtes.ToArray()? Est-ce que vous pouvez éviter le verrouillage? Est-il plus rapide/plus sûr de quelque façon que ce soit? Merci. –
Plus sûr et plus performant ... Le verrouillage n'est pas possible car l'autre thread le supprimera de ma liste, si je bloque la liste, le Join() ne se terminera jamais. Il est recommandé de ne jamais appeler une fonction pendant qu'un verrou est en attente. De plus, je ne peux pas simplement ignorer le verrou car la collection sera modifiée et ma boucle foreach recevra une exception. –
J'ai eu une expérience de première main à ce sujet sur une autre partie du code. J'ai compris que c'était à cause d'un blocage() blocage, mais grâce à vous j'ai pu le résoudre facilement. –