Laden...

GolbalKeyboardHook: Delegat wird vom GC abgeräumt

Erstellt von manunidi vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.913 Views
M
manunidi Themenstarter:in
221 Beiträge seit 2008
vor 12 Jahren
GolbalKeyboardHook: Delegat wird vom GC abgeräumt

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?

1.130 Beiträge seit 2007
vor 12 Jahren

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.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

M
manunidi Themenstarter:in
221 Beiträge seit 2008
vor 12 Jahren

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...

156 Beiträge seit 2010
vor 12 Jahren

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

1.130 Beiträge seit 2007
vor 12 Jahren

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.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

5.742 Beiträge seit 2007
vor 12 Jahren

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.

1.130 Beiträge seit 2007
vor 12 Jahren

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...

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

M
manunidi Themenstarter:in
221 Beiträge seit 2008
vor 12 Jahren

Danke für die schnelle Hilfe. Ich habs hinbekommen. War komplettes Neuland für mich, aber jetzt versteh ich es 😃

S
1 Beiträge seit 2011
vor 12 Jahren
Lösung

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 😕

49.485 Beiträge seit 2005
vor 12 Jahren

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