Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Events mit Lock werfen NullReferenceException
FischeFr
myCSharp.de - Member



Dabei seit:
Beiträge: 3

Themenstarter:

Events mit Lock werfen NullReferenceException

beantworten | zitieren | melden

Hallo zusammen!

Ich habe ein kleines Projekt gestartet, bei dem PowerShell-Code in einem C#-Programm ausgeführt wird. In Sachen Events könnte ich jetzt von euch etwas Hilfe gebrauchen. Ich kämpfe den ganzen Tag schon mit folgender Fehlermeldung:
Fehler
System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.ArgumentNullException: Der Wert darf nicht NULL sein.
bei System.Threading.Monitor.Enter(Object obj)
bei PSService.PowershellService.ServiceEventsForScript.add_Stop(EventHandler`1 value)
--- Ende der internen Ausnahmestapelüberwachung ---
bei System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
bei System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
bei System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
bei System.Reflection.EventInfo.AddEventHandler(Object target, Delegate handler)
bei System.Management.Automation.PSLocalEventManager.ProcessNewSubscriber(PSEventSubscriber subscriber, Object source, String eventName, String sourceIdentifier, PSObject data, Boolean supportEvent, Boolean forwardEvent)
bei System.Management.Automation.PSLocalEventManager.SubscribeEvent(Object source, String eventName, String sourceIdentifier, PSObject data, ScriptBlock action, Boolean supportEvent, Boolean forwardEvent, Int32 maxTriggerCount)
bei Microsoft.PowerShell.Commands.ObjectEventRegistrationBase.EndProcessing()
bei System.Management.Automation.CommandProcessorBase.Complete()

Dieses Problem trifft auf, wenn das PowerShell-Skript versucht, einen Subscribe-Vorgang auf ein von mir bereitgestelltes Event auszuführen. Ein entsprechender (sinnfreier) Versuchscode sieht folgendermaßen aus:

            public event EventHandler<EventArgs> StopEvent;
            public event EventHandler<EventArgs> Stop
            {
                add
                {
                    lock (StopEvent)
                    {
                        StopEvent += value;
                    }
                }
                remove
                {
                    lock (StopEvent)
                    {
                        StopEvent -= value;
                    }
                }
            }

Vermutlich spielt die PowerShell-Zeile keine Rolle, aber vollständigkeitshalber lautet sie wie folgt:
Register-ObjectEvent -InputObject $Host.PrivateData.Events -EventName 'StopEvent' -SourceIdentifier 'PSService_Stop' -ErrorAction Stop | Out-Null

Bei Verwendung von "StopEvent" klappt alles prima, bei "Stop" bekomme ich die obige Fehlermeldung. "StopEvent" ist hier nur testweise eingefügt. Das "echte" Event, an das weitergeleitet werden muss ist in einer anderen Klasse. Hat von euch jemand eine Idee, was da schief läuft?
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15510
Herkunft: BW

beantworten | zitieren | melden

Der Fehler ist, dass Du dem lock() ein Null übergibst; das sieht man auch in der Fehlermeldung.
Und StopEvent ist hier wohl null.

lock() sollte man immer mit Lockobjekten verwenden; nicht mit "irgendwas".
Der Sinn, wieso Du hier überhaupt lockst, erschließt sich mir nicht.

[Artikel] Debugger: Wie verwende ich den von Visual Studio?
private Nachricht | Beiträge des Benutzers
FischeFr
myCSharp.de - Member



Dabei seit:
Beiträge: 3

Themenstarter:

beantworten | zitieren | melden

Ich danke dir!

Ich war wohl so vertieft, dass ich immer die falsche Zeile angesehen hab. Null locken ist natürlich keine gute Idee :)

Das Locking hab ich von einem Beispiel von Microsoft (blind) übernommen.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15510
Herkunft: BW

beantworten | zitieren | melden

Zitat von FischeFr
Das Locking hab ich von einem Beispiel von Microsoft (blind) übernommen.

Kann mir nicht ganz vorstellen, dass das das reine Beispiel von Microsoft ist.
Und wenn doch, dann gibt es in den Samples die Möglichkeit Fehler zu korrigieren.
Link zum Beispiel?
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1767
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Ich hab beim suchen nach locking bei C# nur das Beispiel gefunden:https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/keywords/lock-statement

Ansonsten wäre es ratsam, wenn du als Lock Objekt eine Instanz von Object verwendest.
Einen EventHandler sollte man hier nicht als Lock Objekt missbrauchen, ist kein guter Stil und nicht sinn eines Event Handlers.

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15510
Herkunft: BW

beantworten | zitieren | melden

Zitat von T-Virus
Ich hab beim suchen nach locking bei C# nur das Beispiel gefunden:https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/keywords/lock-statement
Warten wir doch mal ab, welches Beispiel er nennt. Raten oder für ihn suchen bringt ja nichts ;-)
Zitat von T-Virus
Einen EventHandler sollte man hier nicht als Lock Objekt missbrauchen, ist kein guter Stil und nicht sinn eines Event Handlers.
Mit Stil hat das wenig zutun; es ist technisch falsch.
Der Sinn eines Eventhandlers wird durch das lock() auch nicht beeinflusst.
Aber er hat es ja ohnehin bereits nun verstanden.
private Nachricht | Beiträge des Benutzers
FischeFr
myCSharp.de - Member



Dabei seit:
Beiträge: 3

Themenstarter:

beantworten | zitieren | melden

Danke zusammen - jetzt funktionierts.

Der Lock auf einen Event ist gleich mehrfach dämlich:
    - ist null, wenn noch keine Subscription vorliegt
    - Object wird bei jedem Subscribe durch ein neues (Ergebnis von Delegate.Combine) ausgetauscht

Eigentlich weiß ich das, aber ich bin einfach gestern zu lange vorm Rechner gesessen. War geistig nicht mehr ganz fit

Ich hatte folgendes Beispiel gemeint. Allerdings benutzen die ein "lockObject", das im Beispiel nicht deklariert wird. Hier das Event zu benutzen war wohl auf meinem eigenen Mist gewachsen.
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-implement-custom-event-accessors
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15510
Herkunft: BW

beantworten | zitieren | melden

Vielleicht nicht 100% zum Copy geeignet, aber das Objekt heisst ja objectLock; das sagt ja ziemlich genau, was es ist.
Und wenn man dann in die Doku von lock() schaut, wird es auch gezeigt.

Daher muss ich Dir sagen, dass Du da der Doku unrecht getan hast; die Doku zeigt nicht, dass Du den Event nehmen sollst.
Sonst würde hier ja auch lock (PreDrawEvent) stehen und nicht lock (objectLock) ;-)
private Nachricht | Beiträge des Benutzers