2011-10-27 13 views
8

Mam naprawdę, bardzo dziwny błąd, którego nigdy nie udało mi się ustalić (zdarza się to bardzo rzadko). Zasadniczo, mam aplikację C#, która losowo rzuciła nieznany wyjątek przy wyjściu. Udało mi się go złapać w debuggera tym razem, a okazuje się, że dzwoni Application.Exit() jest rzucanie System.InvalidOperationException z następującym komunikatem:System.InvalidOperationException ze względu na modyfikację kolekcji podczas wywołania Application.Exit()

Pierwsza szansa wyjątek typu „System.InvalidOperationException” wystąpił w mscorlib. dll

Dodatkowe informacje: Kolekcja została zmodyfikowana; operacja wyliczania może nie zostać wykonana.

nie jestem pewien co to zbiór, który został rzekomo jest modyfikowana, lub kto to był, że go modyfikować.

Ślad stosu nie jest bardzo pomocne:

mscorlib.dll System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext() + 0x13f bajtów System.Windows System.Windows.Forms.dll!. Forms.Application.ExitInternal() + 0x112 bajtów System.Windows.Forms.Application.Exit System.Windows.Forms.dll! (System.ComponentModel.CancelEventArgs e) + 0x65 bajtów

Każdy pomysł jak ja może dowiedzieć się, który ArrayList został zmodyfikowany? Nie sądzę, że jest to coś, co robię jawnie, bardziej prawdopodobne działanie, które robię, modyfikowanie podstawowego stanu platformy .NET w trakcie operacji, której MS nie oczekiwał ..

+0

To brzmi jak kolekcja formularzy. IIRC Widziałem już to wcześniej, ale nie pamiętam żadnych szczegółów, przepraszam. – leppie

+1

Co robi aplikacja podczas zamykania systemu? Czy mógłbyś podać kod? – Fischermaen

+0

Nic, naprawdę ... W momencie, gdy naciskałem przycisk wyjścia, aplikacja była w stanie bezczynności, bez wątków działających w tle. –

Odpowiedz

17

Niezwykłe , nigdy wcześniej tego nie widziałem. Metoda Application.ExitInternal() iteruje kolekcję Application.OpenForms. Oczywiście ta kolekcja jest modyfikowana podczas jej wykonywania. Istnieje kilka możliwych przyczyn takiego stanu rzeczy. Mogę wymyślić tylko jeden. Jeden z twoich formularzy zastąpił metodę OnFormClosing() lub zasubskrybował zdarzenie FormClosing. I robi coś, co modyfikuje kolekcję OpenForms. Może to być wyrzucanie obiektu formularza lub tworzenie nowej instancji formularza lub modyfikowanie właściwości formularza, która powoduje ponowne utworzenie okna, na przykład ShowInTaskbar.

Nie znajdziesz tego kodu z powrotem w stosie wywołań. Przejrzyj swój kod On/FormClosing. Skomentuj kod, jeśli nie możesz go szybko znaleźć.

+0

Mam dość skomplikowany kod FormClosing, który czasami otwiera skrzynkę wiadomości. W każdym razie wydaje mi się, że zmiana z Application.Exit() na this.Close() sprawdziła się przy problemach, nie wymagając od mnie zmiany zawartości FormClosing. –

+2

@Hans Passant, mając dokładnie ten sam problem; i oczywiście pokazałem okno komunikatu w mojej metodzie 'Form_CLOSING'. I bum, ta sama modyfikacja kolekcji. Jak głupio. Przeniesiono go do 'Form_CLOSED' i dobrze. Trochę dziwne, ale hej, brawo w tym wyniku. –

+1

To był też dokładnie mój problem, MessageBox w OnClosing unieważniał iterator formularzy Open.Axit Application.Exit. Przeniesienie go do OnClosed naprawiono! – Blindy

0

Po prostu spędziliśmy wiele dni na tym problemie ... gdzie dostaliśmy wyjątek "System.InvalidOperationException", a także aplikację (w tym przypadku przy użyciu biblioteki twain z DynamSoft). Najwyraźniej nie powinniśmy wywoływać CLOSE() po wywołaniu application.exit. Komentowanie zamknięcia sprawiło, że wyjątek zniknął i sprawił, że aplikacja skończyła się normalnie. Wizualnie aplikacja wyświetli dziwne okienko z wiadomością Microsoft, mówiąc: "czy chcesz przesłać więcej informacji o tym problemie" - CO PROBLEM? nie wyświetlał niczego wcześniej, więc poszliśmy przekopać się przez ślady stosu.

   Utils.Logger.Info("", "AsystScanner/dynamicDotNetTwain2_OnPostAllTransfers"); 
       Utils.Logger.Info("Closing down application!", "AsystScanner/dynamicDotNetTwain2_OnPostAllTransfers"); 

       // caller should close down app, added 3/3/15 
       dynamicDotNetTwain2.CloseSource(); 
       dynamicDotNetTwain2.CloseSourceManager(); 

       System.Windows.Forms.Application.Exit(); 
no no! don't do a close here. 
       //try 
       //{ 
       // Close(); 
       //} 
       //catch (Exception ex) 
       //{ 
       // MessageBox.Show(ex.Message + " Routine=dynamicDotNetTwain2_OnPostAllTransfers/Close() statement failed. [EJS1503031630]"); 
       //} 
       return; 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message + " Routine=dynamicDotNetTwain2_OnPostAllTransfers [EJS1503031631]"); 
      }