event handler problem, nicht erlaubter zugriff auf anzeige.



  • HI

    das mit den klassen hat jetzt super funktioniert, deshalb habe ich mich jetzt an event handler rangetraut. das compilieren hat super funktioniert, bloß bei der ausführung (achtung knuddelbaer 🙂 ) geht was nicht.

    ich habe es im debugmodus verfolgt und bin darauf gestoßen was nicht geht.

    die entwicklungsumgebung lieferte mir als Fehlermeldung:

    Zusätzliche Informationen: Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement listView1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

    ok jetzt noch code.
    den Eventhanlder hab ich so definiert.

    public:
    delegate void NeueDatenVorhandenEventHandler();
    	event NeueDatenVorhandenEventHandler^ NeueDatenVorhanden;
    

    in der anderen klasse.

    Programm1->Serialgerät->NeueDatenVorhanden+=gcnew Serialgerät3::NeueDatenVorhandenEventHandler(this, &Form1::DatenInListView);
    
    public: void DatenInListView() {
    ...
    Form1::listView1->Items->Add(lvi);
    geändert=true;
    }
    

    ich habe schon ein wenig rumgetestet, von private auf public gestellt und sowas. ich glaube da fehlt ein puzzelteil zum verständniss. warum wird eine methode die von einer anderen aufgerufen wird nicht richtig ausgeführt obwohl wenn sie es alleine macht es geht?
    an public oder privat scheint es nicht zu liegen.



  • Naja

    Der Zugriff auf das Steuerelement listView1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

    sagt Dir eigentlich schon das Du aus einem anderen Thread heraus auf die listView1 zugreifst.

    Kurz: Thread1 besitzt die ListView1 und Thread2 greift darauf zu.

    Die Frage wäre jetzt erst einmal: Startest Du irgendwo einen anderen Thread ?

    Wenn ja, kann das hier helfen:
    http://msdn2.microsoft.com/de-de/library/ms171728(VS.80).aspx

    (Mit Threads hab ich bisher sehr wenig gemacht)



  • danke knuddelbaer, den artikel hab ich nciht gefunden 😞 du bist gut.

    ich hab einfach die CheckForIllegalCrossThreadCalls-Eigenschaft vom listview auf false gesetzt damit geht es, das listview kann eh keiner ändern wenn er misst, sollte also auch sicher sein. hoffe das kommt nicht mit den neuzeichnen oder so in konflikt man weiß ja nie 🙂

    gruß
    LoM



  • Nö, ich bin nicht gut. Du hättest einfach nur die Fehlermeldung bei Google eingeben müssen:

    Der Zugriff auf das Steuerelement erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

    http://www.google.de/search?sourceid=navclient&hl=de&ie=UTF-8&rls=GGLJ,GGLJ:2006-39,GGLJ:de&q=Der+Zugriff+auf+das+Steuerelement+erfolgte+von+einem+anderen+Thread+als+dem+Thread%2C+für+den+es+erstellt+wurde.+

    Ich würde das Problem beheben, nicht verstecken. Durch abschalten des "meckerns" ists zwar friedlicher, aber das Problem holt Dich eventuell irgendwann ein und lässt sich nur sehr sehr mühsig aufklären.



  • du hast ja recht, vieleicht sollte ich den zugriff wirklich threadsicher machen. ich habe auch nicht explezit threads programmiert. das teil wird von im endeffekt von windows comport treiber gestartet, vieleicht kommt da das mit den thread her.



  • Hmm... Wenn Du das raus bekommen hast Poste es mal.
    Solang es unbekannt ist - schau mal wie aufwendig es wird das Threadsicher zu machen. Wärst dann IMHO zumindest auf der sicheren Seite.



  • ich habe jezt soweit glaube alles durchgelesen nur komme ich mit den beiden zeilen in c# nicht klar

    SetTextCallback d = new SetTextCallback(SetText);
                    this.Invoke(d, new object[] { text });
    

    😞 scheint eine andere sprache zu sein.

    einer eine Idee?



  • guten morgen

    ich habe jetzt eine lösung gefunden die funktioniert. kann leider noch nicht erklären warum. hoffe einer von euch kann mir weiterhelfen 🙂

    delegate void ListWarten();
    void SetText() {
    	ListWarten^ d=gcnew  ListWarten(this,&Form::Form1::DatenInListView);
    	if (listView1->InvokeRequired) {
    	listView1->BeginInvoke(d);
    	}
    	else {
    	DatenInListView();
    	}
    }
    

    Das ereigniss löst die oben beschriebene methode SetText aus. so gibt es keine fehlermeldung beim compilieren und beim ausführen auch nicht, auch die daten kommen in den listview an, sollte also funktionieren.

    gruß
    LoM



  • Naja, die MSDN sagt zu InvokeRequired:

    Ruft einen Wert ab, der angibt ob der Aufrufer beim Aufruf von Methoden des Steuerelements eine Aufrufmethode aufrufen muss, da sich der Aufrufer in einem anderen Thread als dem befindet, in dem das Steuerelement erstellt wurde.

    Du solltest aber noch EndInvoke aufrufen. Zwar sagt die MSDN

    Wenn im Aufruf der BeginInvoke-Methode eine Rückrufmethode angegeben wurde, wird diese beim Beenden der Zielmethode aufgerufen. Die EndInvoke-Methode wird im Rückruf dazu verwendet, den Rückgabewert und ggf. die In/Out-Parameter abzurufen. Wenn beim Aufrufen von BeginInvoke keine Rückrufmethode angegeben ist, kann EndInvoke von dem Thread aufgerufen werden, der BeginInvoke aufgerufen hat.

    das es zum abholen von Rückgabewerten verwendet wird, aber ich denke es ist besser EndInvoke auch dann aufzurufen, wenn man keine Rückgabewerte verwendet.

    (Vllt. kann jemand mit Erfahrung im Bereich Threading was zu sagen).

    Fände es prima , wenn man den Titel anpasst und das in die FAQ packt.



  • Endivoke möchte eine variable definiert bekommen. scheint also wirklich nur bei rückgabewerten zu funktionieren.



  • public:
    virtual Object^ EndInvoke (
    	IAsyncResult^ asyncResult
    ) sealed
    

    Das IAsyncResult, das einen bestimmten asynchronen Aufrufvorgang darstellt, der beim Aufrufen von BeginInvoke zurückgegeben wird

    Wie gesagt, ich kann Dir im Moment nur sagen, das mir das Gefühl sagt, das es falsch ist BeginInvoke ohne EndInvoke zu benutzen.

    Siehe auch:
    http://groups.google.de/group/microsoft.public.de.german.entwickler.dotnet.csharp/browse_thread/thread/5bb74f74c29c707a/7a9f04e73128bce9?lnk=st&q=EndInvoke&rnum=2&hl=de#7a9f04e73128bce9

    http://groups.google.de/group/microsoft.public.de.german.entwickler.dotnet.csharp/browse_thread/thread/5bb74f74c29c707a/7a9f04e73128bce9?lnk=st&q=EndInvoke&rnum=2&hl=de#7a9f04e73128bce9

    Das Thema wird wohl umfangreicher da u.U. ein Callback nötig ist um heraus zu finden wann genau EndInvoke aufgerufen werden soll.

    Das Thema ist IMHO recht Umfangreich, ich bekomme es derzeit auf die schnelle nicht Quergelesen um hier etwas zu sagen.

    Also hoffen wir, das jemand anderes was dazu sagen kann. Generell kann es aber nicht schaden das Thema genauer zu lesen (wenn dann die Zeit für da ist).


Anmelden zum Antworten