Ich muss eine Reihe von Aufrufen an einen einzelnen Webdienst für verschiedene Zeiträume tätigen und eine verkettete Ergebnismenge generieren. Ich möchte die Anrufe parallel machen, um den Prozess zu beschleunigen, obwohl ich in diesem Bereich wenig Erfahrung habe.Code läuft parallel in LinqPad, aber nicht in der Konsolen-App ... warum?
Ich habe verschiedene Techniken ausprobiert, aber basierend auf der Ausführungszeit laufen meine Codeaufrufe weiterhin in der Reihenfolge, wenn ich sie in einer Visul Studio Konsolenanwendung starte. Damit meine ich, wenn ein Anruf für einen einmonatigen Datumsbereich 15 Sekunden dauert, dann dauern drei der einmonatigen Anrufe, die angeblich parallel laufen, 45 Sekunden.
Aber hier ist der Teil, der mich wirklich überraschte: Ich begann den genau gleichen Code in LinqPad für das Debugging zu laufen. Und siehe, in LinqPad läuft derselbe Code parallel! Für 3 Monate zu telefonieren dauert ca. 15 Sekunden!
Jetzt kratze ich meinen Kopf, wie das sein könnte. Ich habe versucht, die LinqPad-Version in ein neues Conole-Projekt zu kopieren (um zu überprüfen, dass in beiden Versionen wirklich alles gleich ist), aber das Verhalten ändert sich nicht.
Ich würde mich über Vorschläge freuen. Ich bin nicht sicher, welcher Code für die Frage relevant ist, aber ich habe eine etwas vereinfachte Version der Web-Service-calling-Klasse unten enthalten:
class Importer
{
public List<FuncDetails> GetAllData(DateRange[] intervals)
{
Task<List<PropFuncsType>>[] tasks = intervals
.ToList()
.Select(interval => GetDataForIntervalAsync(interval.StartDate, interval.EndDate))
.ToArray();
var result = new List<ResultDataTable>();
Task.Factory.ContinueWhenAll(tasks, results => { foreach (var output in results) { result.AddRange(output.Result); } })
.Wait();
return result.SelectMany(x => x.ResultDataRow).ToList();
}
async static private Task<List<ResultDataTable>> GetDataForIntervalAsync(DateTime startDate, DateTime endDate)
{
var service = new ServiceClient();
var result = await service.getDataAsync(new ServiceRequest()
{
startDate = string.Format("{0:yyyy-MM-dd}", startDate),
endDate = string.Format("{0:yyyy-MM-dd}", endDate)
}
);
return result.ServiceResponse.ToList();
}
}
Haben Sie "ServicePointManager.DefaultConnectionLimit" überprüft? –
Das war's! 'ServicePointManager.DefaultConnectionLimit' ist effektiv ein globaler Eintrag und der LinqPad-Host muss einen hohen Wert außerhalb meines Codes gesetzt haben. Ich habe mir zwei Tage lang den Kopf darüber geschlagen. Bitte machen Sie Ihren Kommentar zu einer Antwort, damit ich Ihnen einen angemessenen Kredit geben kann! –