2009-02-23 20 views
108

Otrzymuję komunikat o błędzie, którego nie mogę rozwiązać. Pochodzi z Visual Studio lub debuggera. Nie jestem pewien, czy ostateczny warunek błędu jest w VS, debugger, mój program lub bazy danych.Visual Studio: ContextSwitchDeadlock

To jest aplikacja dla systemu Windows. Nie jest to 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ę: "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żdej linii wykorzystuje wartość klucza (HIC#) z tabeli jako parametr SqlCommand. Polecenie służy do utworzenia SqlDataReader, który zwraca jedną linię. Dane są porównywane. W przypadku wykrycia błędu wiersz jest dodawany do drugiej tabeli DataTable.

Błąd wydaje się być związany z czasem działania procedury (tj. Po 60 sekundach), a nie z liczbą błędów. Nie sądzę, żeby to był problem z pamięcią. Żadne zmienne nie są zadeklarowane w pętli. Jedynymi stworzonymi obiektami są SqlDataReaders i są one w użyciu struktur. Add System.GC.Collect() nie przyniósł żadnego efektu.

Baza danych jest witryną SqlServer na tym samym laptopie.

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

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

Jakieś pomysły, ktoś?

Pełna błędu Tekst: CLR nie był w stanie przejść od kontekstu COM 0x1a0b88 kontekstu COM 0x1a0cf8 przez 60 sekund. Wątek, który jest właścicielem kontekstu docelowego/mieszkania, najprawdopodobniej robi czekanie bez pompowania lub przetwarza bardzo długą operację bez pompowania komunikatów systemu Windows. Sytuacja ta ma ogólnie negatywny wpływ na wydajność, a nawet może prowadzić do braku reakcji aplikacji lub zużycia pamięci przez cały czas. Aby uniknąć tego problemu, wszystkie wątki z pojedynczym gwintowanym mieszkaniem (STA) powinny korzystać z podstawowych operacji pompowania (takich jak CoWaitForMultipleHandles) i rutynowo pompować komunikaty podczas długotrwałych operacji.

Odpowiedz

184

The ContextSwitchDeadlock nie musi oznaczać, że Twój kod ma problem, tylko że istnieje potencjał. Jeśli przejdziesz do Debug > Exceptions w menu i rozwiń Managed Debugging Assistants, znajdziesz ContextSwitchDeadlock jest włączony. Jeśli to wyłączysz, VS nie będzie już ostrzegał, gdy przetwarzanie przedmiotów zajmuje dużo czasu. W niektórych przypadkach możesz skutecznie działać długo. Przydaje się także debugowanie i zatrzymanie na linii podczas przetwarzania - nie chcesz, aby narzekało, zanim będziesz miał szansę zagłębić się w problem.

+4

Tuż! Dzięki. Musiałem przejść do Dostosuj i dodaj Wyjątki do menu Debuguj. Nie jest to najbardziej intuicyjny aspekt interfejsu użytkownika. Narzędzia \ Dostosuj, a następnie Zmień układ poleceń (przycisk), a następnie wybierz opcję Debuguj z menu rozwijanego w prawym górnym rogu, a następnie przycisk Dodaj (przycisk). Whew! – SeaDrive

+0

Tak, wygląda na to, że niektóre instalacje mają to w menu, a niektóre nie. Zauważyłem to również z innymi przydatnymi elementami menu, a ja jeszcze nie wiem, co je domyślnie włącza i wyłącza. – Pedro

+46

'ctrl-alt-e' wyświetla okno dialogowe wyjątku. –

8

Wygląda na to, że robisz to w głównym wątku UI w aplikacji. Wątek interfejsu użytkownika jest odpowiedzialny za przesyłanie komunikatów systemu Windows podczas nadejścia, a ponieważ jest on zablokowany w wywołaniach baz danych, nie może tego zrobić. Może to powodować problemy z wiadomościami ogólnosystemowymi.

Powinieneś przyjrzeć się spawowi wątku tła dla długotrwałej operacji i umieszczeniu pewnego rodzaju okna dialogowego "Jestem zajęty" dla użytkownika, kiedy to się stanie.

5

Jeśli nie chcesz wyłączać tego wyjątku, wystarczy, że aplikacja przepompuje niektóre wiadomości co najmniej raz na 60 sekund. Zapobiegnie to wystąpieniu tego wyjątku. Spróbuj wywoływać System.Threading.Thread.CurrentThread.Join (10) raz na jakiś czas. Są inne połączenia, które możesz wykonać, aby komunikaty mogły się pompować.

+0

Czy możesz wyjaśnić, dlaczego to pomaga? – rolls

+0

To nie zadziała, mam pętlę aktualizującą interfejs użytkownika i nadal otrzymuję komunikat o błędzie. – htm11h

13

Jak powiedział Pedro, problem z debuggerem uniemożliwia pompę komunikatów, jeśli przechodzisz przez kod.

Ale jeśli wykonujesz długo działającą operację na wątku UI, wywołaj Application.DoEvents(), która jawnie pompuje kolejkę komunikatów, a następnie zwraca kontrolę do aktualnej metody.

Jeśli jednak to robisz, poleciłabym przejrzeć Twój projekt, aby móc wykonywać przetwarzanie poza wątkiem interfejsu użytkownika, dzięki czemu interfejs użytkownika pozostanie niezły.

0

Powyższe rozwiązanie jest dobre w niektórych scenariuszach, ale istnieje inny scenariusz, w którym dzieje się to podczas testów jednostkowych i próbujesz wykonać "Debugowanie wybranych testów" w Eksploratorze testów, gdy rozwiązanie nie jest ustawione na Debugowanie.

W takim przypadku musisz zmienić swoje rozwiązanie z wersji Release lub cokolwiek innego na Debugowanie w tym przypadku. Jeśli to jest problem, zmiana "ContextSwitchDeadlock" naprawdę nie pomoże.

Tęskniłem za tym, ponieważ komunikat o błędzie był tak nieprzyjemny, że nie sprawdziłem oczywistej rzeczy, która była ustawieniem Debugowania!

0

W hiszpańskiej wersji programu Visual Studio 2017.

"Depurar" -> "Ventanas" -> "Configuración de Excepciones"

i szukać "ContextSwitchDeadlock". Następnie odznacz to. Albo skrót

Ctrl + D, E

Najlepsza.

0

Problem ten można rozwiązać poprzez odznaczenie contextswitchdeadlock z

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