J'ai une application de console filetée qui fonctionne bien, mais son architecture doit être améliorée, et j'aimerais recevoir des commentaires.Verrouillage C# et question de conception de filetage général
Actuellement, le programme charge une liste de données et segmente ces données en partitions (un morceau pour chaque thread). Le programme initialise ensuite un nouveau thread à l'aide de ThreadPool et lui transmet UN segment des données partitionnées sur lequel opérer.
Tout fonctionne bien ... sauf:
Certains des fils échouent ... en raison de problèmes de réseau, ou des exceptions irrécupérables. C'est un comportement attendu et pas un bug.
J'ai maintenant besoin d'un moyen (si le thread échoue) de récupérer le segment de données de ce thread et de le fournir à un autre thread de travail afin qu'il ne devienne pas orphelin. Je suis sûr qu'il existe des moyens de le faire, c'est-à-dire de partager des données entre les threads, etc., mais je pense qu'il y a une meilleure approche. Au lieu de segmenter les données au préalable et de les passer à chaque thread, je pouvais partager une collection statique de ces données entre tous les threads. C'est plus élégant, mais introduit de nouveaux problèmes de synchronisation que l'ancienne approche n'avait pas à s'inquiéter. A.) Que pensez-vous de cette approche par rapport à l'ancienne?
B.) Si cette approche est bonne, comment puis-je verrouiller l'accès à la collection statique partagée.
Lorsque le thread est initialisé, je peux verrouiller la collection et enlever un segment des données juste pour ce thread. La collection statique serait maintenant REDUITE par la quantité sautée pour ce fil. Après ÉCHEC du thread, je pourrais réaffecter ce segment de données à la collection partagée en le verrouillant à nouveau et en repoussant les données dans la collection pour que d'autres threads tentent de les traiter.
Par exemple: (non testé pseudocode)
void Process(object threadInfo)
{
lock(StaticCollection)
{
var segment = StaticCollection.Take(100);
StaticCollection.Remove(StaticCollection.Where(item => segment.Contains(item)))
}
foreach(var seg in segment)
{
// do something
}
// reallocate the thread's data on failure
if(unrecoverableErrorOccurred)
{
lock(StaticCollection)
{
StaticCollection.Add(segment);
}
}
}
Am I sur la bonne voie avec cela? Il me semble qu'un thread peut supprimer des éléments en même temps qu'un autre thread réalloue des éléments ... ou un verrou sur une collection STATIC signifie qu'aucun autre thread ne peut accéder à cette collection. Donc, Thread A.) a obtenu un verrou dans la PREMIERE partie de la méthode, cela bloquerait-il tous les autres threads d'exécuter la dernière partie de la méthode jusqu'à ce que ThreadA soit complet?
Votre solution est réellement très agréable (à part les appels Take et Remove, vous pouvez envisager d'utiliser une pile réelle). J'aime la solution que vous fournissez car elle vous permettrait également de repousser uniquement les objets qui ont échoué dans la pile ou la file d'attente, et ne nécessite pas d'autre collection pour suivre l'état de traitement de chaque élément. Maintenant, quelqu'un va probablement crier à propos de pourquoi c'est horrible ... – LorenVS
L'opération doit-elle réussir ou échouer en tant que transaction unique? (Et le processus modifie-t-il les données dans le segment sur lequel il opère?) –
Non sur les deux points Jeff. – Scott