ContextSwitchDeadlock wurde in C # als Fehler erkannt

79

Ich führe eine C # -Anwendung aus und erhalte zur Laufzeit die folgende Fehlermeldung:

Die CLR konnte 60 Sekunden lang nicht vom COM-Kontext 0x20e480 zum COM-Kontext 0x20e5f0 wechseln. Der Thread, dem der Zielkontext / die Zielwohnung gehört, führt höchstwahrscheinlich entweder eine Wartezeit ohne Pumpen durch oder verarbeitet einen sehr lang laufenden Vorgang, ohne Windows-Nachrichten zu pumpen. Diese Situation wirkt sich im Allgemeinen negativ auf die Leistung aus und kann sogar dazu führen, dass die Anwendung nicht mehr reagiert oder sich die Speichernutzung im Laufe der Zeit kontinuierlich ansammelt. Um dieses Problem zu vermeiden, sollten alle Single-Threaded-Apartment-Threads (STA-Threads) Pump-Wait-Grundelemente (z. B. CoWaitForMultipleHandles) verwenden und bei langen Betriebsabläufen routinemäßig Nachrichten pumpen.

Kann mir bitte jemand bei dem Problem hier helfen?

Danke vielmals.

Attentäter
quelle

Antworten:

123

Der Haupt-Thread Ihres Programms war eine Minute lang damit beschäftigt, Code auszuführen. Es kümmert sich nicht um seine normalen Aufgaben und pumpt die Nachrichtenschleife. Dies ist illegal, wenn Sie COM-Server in einem Arbeitsthread verwenden: Aufrufe ihrer Methoden können erst ausgelöst werden, wenn Ihr Hauptthread wieder inaktiv ist.

Es sollte gut sichtbar sein, Ihre Benutzeroberfläche sollte wie ein Türnagel tot sein. Windows sollte Ihr Hauptfenster durch einen Geist ersetzt haben, der "Nicht reagiert" anzeigt. Das Schließen des Fensters funktioniert nicht, keine Klickereignisse haben Auswirkungen.

Was auch immer Ihr Haupt-Thread tut, sollte stattdessen von einem Worker-Thread ausgeführt werden. Die BackgroundWorkerKlasse ist dafür gut geeignet. Viele Artikel zur Verwendung finden Sie im Artikel zur MSDN-Bibliothek. Verwenden Sie Debug + Break All, Debug + Windows + Threads, wenn Sie keine Ahnung haben, was der Hauptthread tut.

Eine weitere mögliche Ursache: Installieren Sie unbedingt Service Pack 1, wenn Sie die RTM-Version von VS2005 verwenden.

Hans Passant
quelle
5
+1 für die Erklärung, dass ein solches Arbeitselement in einen sekundären Thread verschoben werden sollte, daher die Lösung, wie dieser Fehler vermieden werden kann (und nicht nur, was den Fehler verursacht).
JYelton
2
Interessant, dass ich gesehen habe, dass einige andere selbst erstellte Anwendungen viel länger hängen geblieben sind als meine, aber ich habe diese Fehlermeldung erhalten, hmmm.
Coops
MSDN-Dokumentation: contextSwitchDeadlock MDA msdn.microsoft.com/en-us/library/ms172233%28v=vs.110%29.aspx
D_Bester
1
Vielen Dank für die ausführliche Erklärung. Die Problemumgehungen, die ich verwendet habe, sind asynchrone Funktionen, was jetzt durchaus Sinn macht. Soweit ich weiß, ist es daher sehr wichtig, einen neuen Thread für lang laufende Vorgänge zu verwalten, insbesondere bei Verwendung von COM.
Anthony Mason
50

Mit den folgenden Schritten können Sie feststellen, welche Operation den Kontextwechsel blockiert und die Anzeige des contextSwitchDeadlock-MDA bewirkt . Beachten Sie, dass ich mich auf Visual Studio 2012 beziehe.

  1. Reproduzieren Sie den Fehler. Dies könnte einige Versuche und Irrtümer beinhalten.
  2. Klicken Sie im angezeigten Managed Debugging-Assistenten auf "OK" und nicht auf "Weiter".
  3. Stellen Sie sicher, dass die Symbolleiste "Speicherort debuggen" aktiv ist, indem Sie mit der rechten Maustaste auf den Andockbereich der Symbolleiste klicken und "Speicherort debuggen" auswählen. Sie sollten eine Dropdown-Liste mit der Bezeichnung "Thread" in der Symbolleiste sehen, wenn diese aktiv ist.
  4. Das ausgewählte Element in der Dropdown-Liste "Thread" sollte ein anderer Thread als der Haupt-Thread sein, da es sich um einen Hintergrund-Thread handelt, der sich darüber beschwert, dass der Haupt-Thread die gesamte Aufmerksamkeit auf sich zieht. Wählen Sie den Haupt-Thread in der Dropdown-Liste aus.
  5. Sie sollten jetzt den Code, der den Kontextwechsel blockiert, im Code-Editor sehen.

Angenommen, Sie entscheiden sich dagegen, den ressourcenintensiven Vorgang von Ihrem Hauptthread zu entfernen. Sehen Sie sich hier einige der anderen Antworten und Kommentare an, bevor Sie dies tun. Sie haben die folgenden Optionen, um die Assistenten für verwaltetes Debuggen zu deaktivieren.

Im Visual Studio Debugger

  1. Sie können einen MDA direkt im MDA-Dialogfeld deaktivieren, das angezeigt wird, wenn der Fehler auftritt, indem Sie das Kontrollkästchen "Unterbrechen, wenn dieser Ausnahmetyp ausgelöst wird" deaktivieren.
  2. Im Dialogfeld "Ausnahmeeinstellungen" anhand der folgenden Anweisungen von MSDN .

... klicken Sie im Menü Debuggen auf Ausnahmen. (Wenn das Debug-Menü keinen Ausnahmebefehl enthält, klicken Sie im Menü Extras auf Anpassen, um ihn hinzuzufügen.) Erweitern Sie im Dialogfeld Ausnahmen die Liste Verwaltete Debugging-Assistenten, und deaktivieren Sie das Kontrollkästchen Ausgeworfen für den einzelnen MDA.

Außerhalb des Visual Studio-Debuggers

  1. Registrierungsschlüssel (maschinenweit, alle betroffenen MDAs)
  2. Umgebungsvariable (Maschinenweit können MDAs angegeben werden)
  3. Anwendungskonfigurationseinstellungen (Anwendungsbereich, MDAs können angegeben werden)

Hinweis: Eine der ersten beiden Optionen muss auf 1 gesetzt werden, damit die dritte Wirkung erzielt wird.

In meinem Fall war das Problem ein Aufruf von ObjectContext.SaveChanges () im Entity Framework innerhalb einer Konsolenanwendung. Mit dem MTAThreadAttribute der angelegten Main()Methode Ausnahme der ContextSwitchDeadlock wurde nicht mehr angehoben . Ich bin mir leider nicht sicher, welche Auswirkungen diese Änderung hat.

Scott Munro
quelle
2
Stimmen Sie für die klare Erklärung zum Finden des Codes ab, der den Prozess blockiert.
Guillaume Schuermans
10

Diese Nachricht zeigt an, dass ein Code von Ihnen versucht, den Thread zu wechseln, und der Ziel-Thread beschäftigt ist. Beispiel: Ein Hintergrund-Thread, der versucht, einen Aufruf an den UI-Thread zu senden, um die Benutzeroberfläche zu aktualisieren, während die Benutzeroberfläche eine Weile eine enge Schleife ausführt.

Um tatsächlich herauszufinden, was los ist, müssen Sie in den Debugger einbrechen und sich alle Threads ansehen und sehen, was sie tun.

Franci Penov
quelle
4

In einigen Fällen:
Debuggen -> Ausnahmen -> Verwaltete Debug-Assistenten
und Deaktivieren des Elements ContextSwitchDeadlock.

Ehsan Zargar Ershadi
quelle
5
Ja, aber wenn Sie einen einmaligen Test schreiben und dieser Ihnen im Weg steht, ist es schön, ihn deaktivieren zu können.
Tod
4
Nein, falsch. Dies ist keine Lösung für das Problem.
Tom W
3
Man muss wie ein Ingenieur denken, nicht wie ein Wissenschaftler !!
Ehsan Zargar Ershadi
4
@Ehsan Ershadi, ein guter Ingenieur, antizipiert und behebt Probleme, schiebt sie nicht unter den Teppich!
Mo Patel
3
LOL. Wenn Sie den Fehler nicht sehen möchten, können Sie einfach woanders als auf Ihrem Monitor suchen. Dies ist der gleiche Ansatz wie bei Ihrer "Lösung". Dies ist keine Lösung. Das ist nur Ignorieren!
neugierigBoy
0

Wählen Sie einfach Ausnahmen aus dem Debug-Menü im Visual Studio 2005-Fenster aus. Das Dialogfeld Edxception wird angezeigt. Wählen Sie den Ausnahmeknoten für verwaltete Debugging-Assistenten aus, wählen Sie dann ContextSwitchDeadlock aus und entfernen Sie die Auswahl aus der geworfenen Spalte. Dadurch wird verhindert, dass vs die ContextSwitchDeadlock-Ausnahme auslöst.

Hoffe das hilft..

Kumari Sony
quelle
60
Dein Arm brennt. Verwenden Sie einfach ein Messer, um den Nerv zu schneiden, der Ihrem Gehirn Schmerzen zufügt. Dadurch werden Sie nicht mehr bemerken, dass Ihr Arm in Flammen steht.
Ozzah
Auf diese Weise kann das Problem vorübergehend gelöst werden. Um dieses Problem vollständig zu lösen, benötigen Sie einige Zeit, um das Design der Anwendung zu überdenken.
Wang Jijun
0

Ich bin auf dieses Problem gestoßen, als ich herausfinden wollte, warum ich OracleDataReadereine Ausnahme ausgelöst habe. Ich dachte, es lag daran, dass es zugewiesen wurde, nullweil die Ausnahme mit einem Parameter zusammenhängt, der `null ist. So tat ich:

while (dr.Read())
{
    while (dr != null)  // <-- added this line
    {
      ...

Es stellte sich heraus, dass das drNIE null war, und so ging die Schleife einfach weiter und weiter, bis diese Nachricht eintraf, und weiter und weiter, weil Sie auf "Weiter" klicken können, um sie fortzusetzen, bis Ihnen der Speicher ausgeht (tun Sie dies nicht - Klicken Sie stattdessen auf "OK". Suchen Sie also nach Speicherlecks, die Daten aus der Datenbank in Schleifen bis ins Unendliche in den Speicher streamen. Der Fehler versucht tatsächlich, Sie vor einem schlechten Szenario zu warnen. Am besten beachten.

vapcguy
quelle
0

Dieser Fehler trat bei mir mehrfach auf und ich habe ihn auf eine Iteration in zurückgeführt DataGridViewRow, in der ich den Kontrollkästchenwert auf true gesetzt habe. Da ich im Debug-Modus lief, hatte ich die Möglichkeit, fortzufahren, sodass ich genau dies tun konnte.

Ich hoffe das hilft jemandem.

Nur Rudy
quelle
0

Angenommen, Sie verwenden Visual Studio, können Sie Ctrl+Alt+Ein das aktuelle Projekt klicken. Das Ausnahmefenster wird mit ausgewählten Managed Debugging-Assistenten angezeigt. Deaktivieren Sie die Option "ContextSwitchDeadlock". Erstellen Sie dann ein aktuelles Projekt.

AShwini Trivedi
quelle