Ich habe eine Konsolenanwendung, die eine Datenbank abfragt und dann einige Datensätze in einer Schleife an eine REST-API sendet (die API unterstützt keine Stapelbuchung, daher muss ich durchgehen jeder Datensatz und Posten einzeln, wenn es relevant ist). Der Zugriff auf die Datenbank ist schnell und problemlos, und auch die API-Post-Schleife entspricht dem Timer, den ich eingerichtet habe. Allerdings benötigt die App selbst nach dem Ende der Arbeit viel Zeit zum Beenden.Console App dauert nach Abschluss der Arbeit sehr lange
Dies begann, nachdem ich Parallel.Foreach
eingeführt, um die Buchung zu beschleunigen. Vor der Verwendung einer nicht-parallelen Schleife dauerte die Veröffentlichung von 1000 Datensätzen durchschnittlich ~ 10 Minuten, aber die App würde zurückkehren und sofort wieder beenden, wenn sie fertig war (wie erwartet). Mit der parallelen Schleife ist diese nach dem Stopwatch
Timer, den ich verwende, auf einen Durchschnitt von ~ 44 Sekunden reduziert, jedoch die App nicht beendet, bis etwa 2 Minuten vergangen sind - ~ 1min15sek nachdem alle Arbeit abgeschlossen ist.
Die App macht nichts "extra". Es gibt main
ein, main
ruft eine Methode auf, um einige Datensätze aus einer Datenbank abzurufen (1-2 Sekunden), leitet 1000 dieser Datensätze an eine andere Methode weiter, die sie durchläuft und jede an die API sendet und dann beendet. Außer, es wird in diesem Fall aus irgendeinem Grund nicht sofort beendet.
Ich setze einen stopwatch
Timer in main
unmittelbar vor dem Aufruf der Buchungsmethode und protokolliere die Zeit unmittelbar nach der Methode zurück, und der Timer richtet sich nach dem Timer innerhalb der Methode, durchschnittlich ~ 46 Sekunden. Die Verzögerung tritt also auf, nachdem die Post-Methode zurückgegeben wurde, aber bevor die main
-Funktion beendet wird, aber es ist nichts definiert, um dies zu tun. Debugging zeigte nichts Außergewöhnliches. Handelt es sich um ein Problem mit der Aufhebung der Zuweisung, das sich auf alle Objekte bezieht, die von der parallelen Schleife erzeugt werden, die "herumhängen"?
Das passiert unabhängig davon, ob ich mit einem Debugger verbunden bin oder die Binärdatei direkt ausführe, wenn sie für die Veröffentlichung erstellt wird (also kein Problem mit der Entfernungsverzögerung). Ich habe mir andere SO-Fragen wie diese angeschaut, aber ihre Ansätze haben keinen Unterschied gemacht. Jede Eingabe würde geschätzt werden.
-Code der Buchungsfunktion:
public ProcessingState PostClockingRecordBatchParallel(List<ClockingEvent> batch, int tokenExpiryTolerance)
{
log.Info($"Attempting to post batch of {batch.Count.ToString()} clocking records to API with an auth token expiry tolerance of {tokenExpiryTolerance} seconds");
try
{
ProcessingState state = new ProcessingState() { PendingRecords = batch };
List<ClockingEvent> successfulRecords = new List<ClockingEvent>();
Stopwatch timer = new Stopwatch();
ServicePointManager.UseNagleAlgorithm = false; //Performance optimization related to RestSharp lib
authToken = Authenticate();
timer.Start();
Parallel.ForEach(state.PendingRecords, pr =>
{
successfulRecords.Add(PostClockingRecord(pr, tokenExpiryTolerance));
});
//Prior non-parallel version
//state.PendingRecords.ForEach(pr =>
//{
// successfulRecords.Add(PostClockingRecord(pr, tokenExpiryTolerance));
//});
state.PendingRecords = state.PendingRecords.Except(successfulRecords).ToList();
state.LastSuccessfulRecord = successfulRecords.OrderBy(r => r.EventID).Last().EventID;
log.Info($"PostClockingRecordBatchParallel - Time elapsed: {new TimeSpan(timer.ElapsedTicks).ToString()}");
return state;
}
catch (Exception ex)
{
log.Fatal($"Failed to post records to API (exception encountered: {ex}).");
throw;
}
}
Danke, genau das, was ich gesucht habe! – Hangman