2 Stimmen

GC.Collect und Multithreading in C#

Ich verwende C# 3.5 und die reaktive Erweiterung, die TPL in C# Version vor 4 unterstützt.

Meine Anwendung ruft GC.Collect() an mehreren Stellen auf (ja, ich weiß, dass ich diese Methode nicht manuell aufrufen sollte, aber bitte lassen Sie diesen Punkt zumindest für diese Frage in Ruhe). Bevor ich die Multithreading-Implementierung eingebaut habe, hat es gut funktioniert. GC.Collect() wird in jedem der Threads aufgerufen, so dass es in einem Multithreading-Kontext aufgerufen wird.

Dann verwende ich den Task, um Multithreading zu implementieren, und ich habe festgestellt, dass die Threads nicht mehr richtig funktionieren, wenn die Anwendung eine Weile läuft und der Speicherverbrauch steigt. Ich erkläre "die Threads nicht mehr richtig funktionieren" aus dem Szenario, dass die CPU-Nutzung auf einem Multi-Core-Computer fällt auf Single-Thread-Ebene, anstatt voll ausgelastet.

Als ich versucht habe, dieses Problem zu lösen, habe ich lediglich den Aufruf GC.Collect() auskommentiert, und diese Änderung bewirkt, dass die Threads gut funktionieren. Ich möchte GC.Collect() ausschalten, es sei denn, wenn ich etwas Großes in meiner Anwendung ausführe, werde ich ohne GC.Collect() in eine OutOfMemory-Ausnahme laufen. Das ist der Grund, warum ich den Aufruf beibehalte.

Könnte mir jetzt jemand erklären, warum GC.Collect() in einem Multithreading-Kontext auf einem Rechner mit viel Speicher ein Multithreading-Problem verursacht? Gibt es eine verwandte Theorie zu diesem Bit? Vielen Dank für die Antwort.

11voto

Kirk Woll Punkte 72923

GC.Collect() führt eine vollständig Garbage Collection, die alle Threads blockieren wird. Sie hat eine Überladung GC.Collect(int) mit der Sie angeben können, welche Generationen Sie sammeln wollen. Zum Beispiel, GC.Collect(0) wird nur die erste Generation erfasst. Ich bin mir nicht sicher, ob das Ihr Problem lösen wird, aber einen Versuch ist es wert.

1voto

Andras Vass Punkte 11288

Als Kirk gesagt hat, hält eine Sammlung alle Fäden inne. Dies kann zu einer gewissen Latenz während der Müllabfuhr führen.

Wenn Sie Ihre Anwendung auf einem Multi-Core-Rechner ausführen, können Sie versuchen, die Server GC zu verwenden, indem Sie sicherstellen, dass Ihre app.config enthält:

<configuration>
 <runtime>
   <gcServer enabled="true"/>
 </runtime>
</configuration>

Man kann stattdessen auch die gleichzeitige GC aktivieren (obwohl ich denke, dass dies die Standardeinstellung für Ihren Fall ist, z.B. eine Desktop-Anwendung auf einem Multi-Core-Rechner, auf dem .NET 3.5 läuft):

<configuration>
  <runtime>
    <gcConcurrent enabled="true" />
  </runtime>
</configuration>

Versuchen Sie es mit ServerGC - es könnte auch Pausen geben, aber diese Pausen könnten kürzer/weniger sein und es könnte einen besseren Gesamtdurchsatz geben. Ihre Erfahrungen können variieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X