Visual Studio: ContextSwitchDeadlock

167

Otrzymuję komunikat o błędzie, którego nie mogę rozwiązać. Pochodzi z programu Visual Studio lub debugera. Nie jestem pewien, czy ostateczny stan błędu występuje w VS, debugerze, moim programie czy bazie danych.

To jest aplikacja dla systemu Windows. To nie jest aplikacja internetowa.

Pierwsza wiadomość od VS to wyskakujące okienko z informacją: „Żadne symbole nie są ładowane dla żadnej ramki stosu wywołań. Nie można wyświetlić kodu źródłowego”. Po kliknięciu otrzymuję komunikat: „ Wykryto ContextSwitchDeadlock ” wraz z długim komunikatem przedstawionym poniżej.

Błąd pojawia się w pętli, która skanuje w dół DataTable. Dla każdego wiersza używa wartości klucza (HIC #) z tabeli jako parametru dla SqlCommand. Polecenie służy do tworzenia SqlDataReader, który zwraca jeden wiersz. Dane są porównywane. W przypadku wykrycia błędu wiersz jest dodawany do drugiego DataTable.

Wydaje się, że błąd jest związany z tym, jak długo trwa procedura (tj. Po 60 sekundach), a nie z liczbą znalezionych błędów. Nie sądzę, żeby to był problem z pamięcią. W pętli nie są deklarowane żadne zmienne. Jedynymi obiektami, które są tworzone, są SqlDataReaders i są one w użyciu struktur. Dodanie System.GC.Collect () nie przyniosło żadnego efektu.

Baza danych to witryna SqlServer na tym samym laptopie.

W formularzu nie ma żadnych fantazyjnych gadżetów ani gadżetów.

Nie jestem świadomy niczego w tym procie, co znacznie różni się od tego, co robiłem dziesiątki razy wcześniej. Widziałem ten błąd wcześniej, ale nigdy w sposób spójny.

Jakieś pomysły, ktoś?

Pełny tekst błędu: CLR nie może przejść z kontekstu COM 0x1a0b88 do kontekstu COM 0x1a0cf8 przez 60 sekund. Wątek będący właścicielem kontekstu / apartamentu docelowego najprawdopodobniej albo wykonuje oczekiwanie bez pompowania, albo przetwarza bardzo długotrwałą operację bez pompowania komunikatów systemu Windows. Ta sytuacja ogólnie ma negatywny wpływ na wydajność i może nawet prowadzić do braku odpowiedzi aplikacji lub ciągłego zwiększania się zużycia pamięci. Aby uniknąć tego problemu, wszystkie wątki z pojedynczym wątkiem (STA) powinny używać elementów podstawowych oczekiwania pompowania (takich jak CoWaitForMultipleHandles) i rutynowo pompować komunikaty podczas długotrwałych operacji.

SeaDrive
źródło

Odpowiedzi:

287

ContextSwitchDeadlockNiekoniecznie oznacza Twój kod ma problemu, po prostu, że istnieje potencjał. Jeśli przejdziesz do Debug > Exceptionsw menu i rozwiniesz Managed Debugging Assistants, zobaczysz, że ContextSwitchDeadlockjest włączona. Jeśli to wyłączysz, VS nie będzie już ostrzegać Cię, gdy przetwarzanie elementów zajmuje dużo czasu. W niektórych przypadkach możesz mieć ważnie długotrwałą operację. Jest to również pomocne, jeśli debugujesz i zatrzymałeś się na linii podczas przetwarzania - nie chcesz, aby narzekał, zanim zdążysz zgłębić problem.

Pedro
źródło
4
Tak jest! Dzięki. Musiałem przejść do Dostosuj i dodać Wyjątki do menu Debugowanie. Nie jest to najbardziej intuicyjny aspekt interfejsu użytkownika. Narzędzia \ Dostosuj, następnie Zmień kolejność poleceń (przycisk), następnie Wybierz debuguj z listy rozwijanej w prawym górnym rogu, a następnie Dodaj (przycisk). Uff!
SeaDrive
81
ctrl-alt-ewyświetla okno dialogowe wyjątków.
Florian Doyon,
1
Wiele nowszych wersji programu Visual Studio (2012, 2010, 2008) i prawdopodobnie kilka wcześniejszych pozwala wybrać podstawowe zastosowanie programu Visual Studio, gdy jest ono uruchamiane po raz pierwszy po instalacji. Ten wybór określa domyślny układ pasków narzędzi, w tym, które kontrolki są widoczne lub ukryte, a nawet które naciśnięcia klawiszy odpowiadają poleceniom. W VS 2010 Kreator importu i eksportu ustawień umożliwia zresetowanie do jednego z dostępnych ustawień domyślnych.
Zarepheth,
4
@ B.ClayShannon - ContextSwitchDeadlock jest specyficzne dla debugera. Wydana wersja exe nie wyświetli tego komunikatu.
Pedro,
9
W VS 2013 Nawiguj za pomocą Debug -> Windows -> Exceptions Settings. Następnie użyj wyszukiwania
Markus Weber
16

Jak powiedział Pedro, masz problem z debugerem uniemożliwiającym pompowanie komunikatów, jeśli przechodzisz przez kod.

Ale jeśli wykonujesz długotrwałą operację w wątku interfejsu użytkownika, wywołaj Application.DoEvents (), która jawnie pompuje kolejkę komunikatów, a następnie zwraca sterowanie do bieżącej metody.

Jeśli jednak to robisz, zalecałbym przyjrzenie się projektowi, abyś mógł wykonać przetwarzanie poza wątkiem interfejsu użytkownika, aby interfejs użytkownika pozostał ładny i zgryźliwy.

Spence
źródło
14

Wygląda na to, że robisz to w głównym wątku interfejsu użytkownika w aplikacji. Wątek interfejsu użytkownika jest odpowiedzialny za pompowanie wiadomości systemu Windows w momencie ich nadejścia, ale ponieważ Twój jest blokowany w wywołaniach bazy danych, nie może tego zrobić. Może to powodować problemy z komunikatami w całym systemie.

Powinieneś przyjrzeć się tworzeniu wątku w tle dla długotrwałej operacji i wyświetlaniu pewnego rodzaju okna dialogowego „Jestem zajęty” dla użytkownika, gdy to się dzieje.

Rob Walker
źródło
13

W programie Visual Studio 2017 odznaczono opcję ContextSwitchDeadlock przez:

Debuguj> Windows> Ustawienia wyjątków

wprowadź opis obrazu tutaj

W systemie Windows ustawień wyjątków: usuń zaznaczenie opcji ContextSwitchDeadlock

wprowadź opis obrazu tutaj

Hassan Rahman
źródło
9

Jeśli nie chcesz wyłączać tego wyjątku, wszystko, co musisz zrobić, to pozwolić aplikacji pompować niektóre wiadomości co najmniej raz na 60 sekund. Zapobiegnie to wystąpieniu tego wyjątku. Spróbuj wywołać System.Threading.Thread.CurrentThread.Join (10) raz na jakiś czas. Istnieją inne połączenia, które możesz wykonać, aby wiadomości były pompowane.


źródło
Czy możesz wyjaśnić, dlaczego to pomaga?
rolki
To nie zadziała, mam pętlę aktualizującą interfejs użytkownika i nadal otrzymuję komunikat o błędzie.
htm11h
1
Nie ma potrzeby używania wartości 10 milisekund, w rzeczywistości, jeśli zamierzasz wywoływać ją wielokrotnie w długotrwałej operacji, znacznie zmniejszy to ogólną wydajność (całkowity czas wykonania). Po prostu podaj zero.
ElektroStudios
Miałem podobny problem. Twoje rozwiązanie działa. Dzięki!
Sk Shahnawaz-ul Haque
2

Powyższe rozwiązanie jest dobre w niektórych scenariuszach, ale istnieje inny scenariusz, w którym dzieje się tak, gdy przeprowadzasz testy jednostkowe i próbujesz „Debugować wybrane testy” z Eksploratora testów, gdy rozwiązanie nie jest ustawione na debugowanie.

W takim przypadku musisz zmienić rozwiązanie z wydania lub cokolwiek, co jest ustawione na debugowanie w tym przypadku. Jeśli na tym polega problem, zmiana „ContextSwitchDeadlock” tak naprawdę nie pomoże.

Sam to przegapiłem, ponieważ komunikat o błędzie był tak nieprzyjemny, że nie sprawdziłem oczywistej rzeczy, jaką było ustawienie debugowania!

Ewan
źródło
1

W hiszpańskiej wersji programu Visual Studio 2017.

„Depurar” -> „Ventanas” -> „Configuración de Excepciones”

i wyszukaj „ContextSwitchDeadlock”. Następnie odznacz to. Lub skrót

Ctrl + D, E

Najlepsza.

kahonmlg
źródło
0

Możesz rozwiązać ten problem, odznaczając opcję contextswitchdeadlock z

Debuguj -> Wyjątki ... -> Rozwiń węzeł MDA -> odznacz -> contextswitchdeadlock

KR Akhil
źródło
0

Otrzymałem ten błąd i przełączyłem zapytania na async (await (...). ToListAsync ()). Teraz wszystko w porządku.

dunwan
źródło