J'essaie d'exécuter plusieurs fonctions qui se connectent à un site distant (par réseau) et renvoient une liste générique. Mais je veux les exécuter simultanément.
Par exemple:
public static List<SearchResult> Search(string title)
{
//Initialize a new temp list to hold all search results
List<SearchResult> results = new List<SearchResult>();
//Loop all providers simultaneously
Parallel.ForEach(Providers, currentProvider =>
{
List<SearchResult> tmpResults = currentProvider.SearchTitle((title));
//Add results from current provider
results.AddRange(tmpResults);
});
//Return all combined results
return results;
}
Comme je le vois, plusieurs insertions dans les "résultats" peuvent se produire en même temps ... Ce qui peut planter mon application.
Comment puis-je éviter ça?
//In the class scope:
Object lockMe = new Object();
//In the function
lock (lockMe)
{
results.AddRange(tmpResults);
}
Fondamentalement, un verrou signifie qu'un seul thread peut avoir accès à cette section critique en même temps.
Vous pouvez utiliser un collecte simultanée .
Le
System.Collections.Concurrent
namespace fournit plusieurs classes de collection thread-safe qui doivent être utilisées à la place des types correspondants dans leSystem.Collections
etSystem.Collections.Generic
_ espaces de noms chaque fois que plusieurs threads accèdent simultanément à la collection.
Vous pouvez par exemple utiliser ConcurrentBag
puisque vous n'avez aucune garantie quant à l'ordre dans lequel les éléments seront ajoutés.
Représente une collection d'objets sécurisée par les threads et non ordonnée.
Les collections simultanées sont nouvelles pour .Net 4; ils sont conçus pour fonctionner avec la nouvelle fonctionnalité parallèle.
Voir Collections simultanées dans le .NET Framework 4 :
Avant .NET 4, vous deviez fournir vos propres mécanismes de synchronisation si plusieurs threads pouvaient accéder à une seule collection partagée. Vous deviez verrouiller la collection ...
... les [nouvelles] classes et interfaces de System.Collections.Concurrent [ajouté dans .NET 4] fournissent une implémentation cohérente pour les problèmes de [...] programmation multithread impliquant des données partagées entre threads.
Pour ceux qui préfèrent le code:
public static ConcurrentBag<SearchResult> Search(string title)
{
var results = new ConcurrentBag<SearchResult>();
Parallel.ForEach(Providers, currentProvider =>
{
results.Add(currentProvider.SearchTitle((title)));
});
return results;
}
Ceci pourrait être exprimé de manière concise en utilisant AsParallel
et SelectMany
:
public static List<SearchResult> Search(string title)
{
return Providers.AsParallel()
.SelectMany(p => p.SearchTitle(title))
.ToList();
}