Ich versuche, mehrere Funktionen auszuführen, die eine Verbindung zu einem Remotestandort (über das Netzwerk) herstellen, und eine generische Liste zurückzugeben. Aber ich möchte sie gleichzeitig ausführen.
Zum Beispiel:
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;
}
Aus meiner Sicht können mehrere Einfügungen in "Ergebnisse" gleichzeitig erfolgen ... Dies kann meine Anwendung zum Absturz bringen.
Wie kann ich das vermeiden?
c#
list
locking
parallel-processing
Shaharmor
quelle
quelle
Antworten:
//In the class scope: Object lockMe = new Object(); //In the function lock (lockMe) { results.AddRange(tmpResults); }
Grundsätzlich bedeutet eine Sperre, dass nur ein Thread gleichzeitig auf diesen kritischen Abschnitt zugreifen kann.
quelle
this
ist nicht die sicherste Wahl für das Sperrobjekt. Verwenden Sie besser ein spezielles privates Objekt :lock(resultsLock)
.locks
kann jedoch die Gesamtausführungszeit verlangsamen. Gleichzeitige Sammlungen scheinen dies besser zu vermeidenSie können eine gleichzeitige Sammlung verwenden .
Sie können zum Beispiel verwenden,
ConcurrentBag
da Sie keine Garantie haben, in welcher Reihenfolge die Artikel hinzugefügt werden.quelle
Für diejenigen, die Code bevorzugen:
public static ConcurrentBag<SearchResult> Search(string title) { var results = new ConcurrentBag<SearchResult>(); Parallel.ForEach(Providers, currentProvider => { results.Add(currentProvider.SearchTitle((title))); }); return results; }
quelle
foreach (var item in currentProvider.SearchTitle((title))) results.Add(item);
Die gleichzeitigen Sammlungen sind neu für .Net 4; Sie sind so konzipiert, dass sie mit der neuen parallelen Funktionalität arbeiten.
Siehe Gleichzeitige Sammlungen in .NET Framework 4 :
quelle
Dies könnte mit PLINQs
AsParallel
undSelectMany
:public static List<SearchResult> Search(string title) { return Providers.AsParallel() .SelectMany(p => p.SearchTitle(title)) .ToList(); }
quelle
SearchTitle
Verbindung zu einem Remote-Standort hergestellt wird. Die Latenz ist um mehrere Größenordnungen langsamer als die Differenz zwischen LINQ und foreach.