Hallo,
ich verwende die Klasse "globalKeyboardhook" im Anhang.
Diese funktioniert auch wunderbar, jedoch erhalte ich bei Eingabe von Zeichen in ein Textfeld in einer Form von diesem Programm ab dem 5. Zeichen folgende Fehlermeldung:> Fehlermeldung:
Für den von der Garbage Collection gesammelten Delegaten vom Typ "outlook2projekt!Utilities.globalKeyboardHook+keyboardHookProc::Invoke" wurde ein Rückruf durchgeführt. Dies kann Anwendungsabstürze, Datenbeschädigung und -verlust zur Folge haben. Beim Übergeben von Delegaten an nicht verwalteten Code müssen die Delegaten von der verwalteten Anwendung beibehalten werden, bis sichergestellt ist, dass sie nie aufgerufen werden.
Hat jemand eine Idee, was das sein könnte?
Ja dein problem ist diese zeile:
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
Genauer gesagt wird für den parameter hookProc implizit ein delegate erstellt und dieser wird dann vom gc eingesackt...
Erstell den delegaten explizit und speicher ihn in nem member.
Hallo,
ich verstehe vom Prinzip her nicht, warum was ein expliziter und impliziter delegate ist und warum ich ihn in nem member speichern soll. Ich muss dazusagen, das ich diese Klasse im Internet gefunden und verwendet habe, und leider momentan auf dem Schlauch stehe. Es währe nett, wenn du mir genauer beschreibst was ich machen muss...
das müsste das hier sein GC.KeepAlive
Du musst dem GC mitteilen, das er den Handle (bzw. Delegate) nicht anschauen darf
GC.ReRegisterForFinalize nicht vergessen
GC.KeepAlive kann man getrost übersetzen als: Mach absolut garnichts, aber tu dabei so, alsob du den parameter verwenden würdest => Keinerlei effekt hier
Was ich meine ist:
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
wird implizit umgewandelt in
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, new globalKeyboardHook.keyboardHookProc(this.hookProc), hInstance, 0);
Man beachte das **new**
.
Du musst nichts weiter tun, als den delegaten zu speichern und das genau so lange, bis du den hook wieder mit UnhookWindowsHookEx entfernst:
this.gepeicherterDeleagte=new globalKeyboardHook.keyboardHookProc(this.hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, this.gepeicherterDeleagte, hInstance, 0);
Es ist zwar eigendlich unnötig, aber wenn du lustig bist kannst nach der zeile mit UnhookWindowsHookEx noch GC.KeepAlive(this.gepeicherterDeleagte); einfügen.
Ansonsten bietet sich auch ein GCHandle an, dass du als Klassenmember hältst:
[...]
Nach der Reservierung können Sie mit einem GCHandle verhindern, dass das verwaltete Objekt vom Garbage Collector erfasst wird, wenn ein nicht verwalteter Client den einzigen Verweis enthält. Ohne ein solches Handle kann das Objekt vom Garbage Collector erfasst werden, bevor es seine Aufgabe für den nicht verwalteten Client abgeschlossen hat.Sie können mit dem GCHandle auch ein fixiertes Objekt erstellen, das eine Speicheradresse zurückgibt und verhindert, dass der Garbage Collector das Objekt im Speicher verschiebt.
Dadurch machst du explizit klar, dass der unmanaged Code das Ding braucht - nicht, dass irgendwann mal jemand "bemerkt", dass da ein nicht benötigtes Feld rumliegt... 😉
Zudem stellt ein _GCHandle _auch sicher, dass der GC das Objekt nicht umkopiert sprich der Pointer ungültig wird.
Zudem stellt ein GCHandle auch sicher, dass der GC das Objekt nicht umkopiert sprich der Pointer ungültig wird.
Das problem stellt sich garnicht erst, da code (marshalling-stub) und daten (mit dem pointer auf den code) in seperaten heaps liegen. Der stub bleibt also so oder so wo er is...
Danke für die schnelle Hilfe. Ich habs hinbekommen. War komplettes Neuland für mich, aber jetzt versteh ich es 😃
Danke für die schnelle Hilfe. Ich habs hinbekommen. War komplettes Neuland für mich, aber jetzt versteh ich es 😃
Kannst du deine Lösung bitte Posten? Hab ein ähnliches Problem und komm nicht drauf 😕
Hallo shark,
grundsätzlich ist es natürlich wünschenswert, wenn Hilfesuchende die Lösung, die sie selbst gefunden haben auch mitteilen. Hier steht aber die Lösung ja schon in der ersten Antwort:
Erstell den delegaten explizit und speicher ihn in nem member.
Wenn das noch nicht konkret genug ist, hat Floste in seiner zweiten Antwort sehr detailliert geschrieben, was man wie ändern muss.
Beachte vor weiteren Nachfragen bitte vorsorglich [Hinweis] Wie poste ich richtig? Punkt 1.1.1.
herbivore