System.InvalidOperationException



  • Hallo,
    habe ein kleines tool gebastelt, welches ein Verzeichnis(Netzlaufwerk) überwacht. Es läuft ständig im tray und so bald Dateien in das Verzeichnis gelangen, poppt es auf und zeigt die neuen Dateien/Ordner in einer Listbox an. Jetzt hatte ich mal den Fall, dass ein Ordner mit vielen Unterordnern und Dateien reingeschoben wurde und da kam eben besagte Exception:

    Eine nicht behandelte Ausnahme des Typs "System.InvalidOperationException" ist in mscorlib.dll aufgetreten.
    
    Zusätzliche Informationen: Die Auflistung wurde geändert. Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden.
    

    Der Fehler ist wiederholbar. Bei nur einer oder wenigeren Dateien klappt alles wunderbar.

    Nun etwas Quellcode:

    Event vom Filesystemwatcher, welches ausgelöst wird wenn eine neue Datei erstellt wird:

    // Define the event handlers.
       private: void OnCreated( Object^ /*source*/, FileSystemEventArgs^ e )
       {	
    
    		m_files->Add(e->FullPath);	/*die gefundene Datei/der gef. Ordner der 
    									Stringcollection hinzufügen*/
    
    	}
    

    Timer-tick-event:

    private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) 
    				 {
    
    					 if (m_files->Count!=0) 	//wenn Dateien gefunden worden		
    					 {		
    
    							DateTime zeit = DateTime::Now;
    							z = zeit.ToString();
    
    							this->Show();
    							if ( this->WindowState == FormWindowState::Minimized )
    							this->WindowState = FormWindowState::Normal;
    
    							for each (String ^str in m_files) 
    							{
    								listBox1->Items->Add(z+" "+str);
    							} 
    
    							m_files->Clear(); /*filecollection mit gefunden Dateien nach 
    												  dem Anzeigen wieder löschen*/
    					 }
    
    				 }
    

    Weis jemand was hier schief läuft?



  • Da kommt ein Event rein, welcher dann das Enum durch "m_files" durcheinander bringt...
    Bringe den Event (OnCreated) in dem gleichen Thread wie die Hauptanwendung, dann hast Du das Problem nicht... (Invoke/BeginInvoke).



  • Kannst du mir das etwas genauer erklären wie ich das anstellen muss? Hab leider von Threadprogrammierung keine Ahnung...



  • Das Event vom FileSystemWatcher wird offenbar auf einem anderen Thread ausgeführt. Es ist ein Problem, dass m_files ungeschützt verändert wird.

    Das einfachste ist mit InvokeRequired und Invoke(..) den Aufruf des Events auf den Gui Thread zu marshallen. Hier findest du ein prinzipielles Bsp. http://www.c-plusplus.net/forum/p1741873#1741873



  • So, habe nun mal wieder Zeit mich mit der Sache zu beschäftigen, leider erfolglos 😞

    Schon bei der ersten Zeile

    System::Threading::Thread^ T1 = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this,&Form1::OnCreated));
                T1->Start();
    

    krieg ich den Fehler:

    1>c:\daten\ms_vs_2010\projects\filewatcher\filewatcher\Form1.h(111): error C3352: "void Filewatcher::Form1::OnCreated(System::Object ^,System::IO::FileSystemEventArgs ^)": Die angegebene Funktion stimmt nicht mit dem Delegattyp "void (void)" überein.
    

    Gleiches kommt dann auch nochmal bei der Zeile mit dem Invoke.

    Was mach ich hier falsch?



  • Deine Methode hat die falsche Signatur. Die Fehlermeldung bzgl. void (void) gesagt, daß die Methode keine Parameter haben darf.
    Alternativ kannst du auch den ParameterizedThreadStart-Delegate benutzen und dort dann eine Methode mit der Signatur "void (object)" verwenden.

    Aber mir scheint, dir fehlen die Grundlagen, um gleich mit Threads und Invoke zu arbeiten! Geschweige denn Windows Forms und Visual C++ MACHT KEINEN SINN!



  • Ich habe doch gesagt das ich von Threadprogrammierung keinen Dunst habe.
    Über Programmiergrundlagen verfüge ich sehr wohl.
    Und ich habe diese Anwendung nun mal damals mit CLI erstellt und keine Lust jetzt alles in C# neu zu schreiben, nur weil man das hier dauernd im Forum unter die Nase gerieben bekommt.


Log in to reply