Frage zu Events bezüglich Zeitpunkt/Reihenfolge der Abarbeitung?

  • C#
  • .NET 5–6

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    Frage zu Events bezüglich Zeitpunkt/Reihenfolge der Abarbeitung?

    Hi,

    ich hab folgendes gemacht. Auf UI Knopfdruck wird ein Sound abgespielt und gleichzeitig der Knopf von 'PlayGrafik' in 'StopGrafik' geändert. Der im Hintergrundliegende Audioplayer feuert ein Event wenn der Sound komplett abgespielt ist. Das Event-'SoundzuEnde' wird im UI aufgefangen und die Knopfgrafik ändert sich wieder in 'PlayButton'. Alles soweit klar und okay.

    Nun hab ich den Code so geändert, dass die abgespielte Sounddatei beim Knopfdrücken 'Play' zu einer List<obj>'ListOfInPlaySounds' hinzugefügt wird und im Fall des Event-'SoundzuEnde' wird das hinzugefügte Obj aus der List<obj>'ListOfInPlaySounds' gelöscht (removed).

    Frage: Was passiert wenn ich mit der Liste List<obj>'ListOfInPlaySounds' in einer anderen Funktion 'arbeite' und jetzt das Event-'SoundzuEnde' feuert und ein Objekt der in 'bearbeitung' befindlichen Liste löscht/löschen soll.

    Passiert das 'mitten drin'?
    Oder wartet der Computer bis die andere Funktion die Liste 'frei gibt' und dann wir der Event Code ausgeführt.
    (Bonus Frage: Wird sowas race condition genannt?)

    LG
    codewars.com Rank: 4 kyu
    Falls die AI mich nicht anlügt :) hat sich das Thema fast schon geklärt!

    ChatGpT 3s Antwort:
    Spoiler anzeigen

    In C#, when you have a method that works on a List<T> (or any collection), and another part of your code triggers an event that wants to delete an object from the same list, the behavior depends on the specific context and how you've implemented your code.

    Synchronization: By default, C# collections like List<T> are not thread-safe. If multiple threads are accessing and modifying the list concurrently, it can lead to issues like race conditions, exceptions, or unexpected behavior.

    Blocking: If one part of your code is iterating through the list or performing an operation on it, and another part tries to delete an object from the list, it can potentially block until the first operation completes. This is because the list's internal data structure may not allow simultaneous modification and enumeration.

    Concurrent Collections: If you need to work with collections in a multithreaded environment, you should consider using thread-safe collections from the System.Collections.Concurrent namespace, such as ConcurrentBag<T>, ConcurrentQueue<T>, or ConcurrentDictionary<TKey, TValue>. These collections are designed to allow safe concurrent access and modification.

    Locking: Alternatively, you can use explicit locking mechanisms (e.g., lock keyword) to synchronize access to the list. This way, you can ensure that only one part of your code accesses the list at a time. However, this approach may introduce potential performance bottlenecks if used excessively.

    Here's an example of using locking to synchronize access to a list:

    csharpCopy code
    private List<YourObject> yourList = new List<YourObject>();
    private object listLock = new object();

    public void SomeMethod()
    {
    lock (listLock)
    {
    // Perform operations on yourList
    // ...
    }
    }

    public void EventHandler()
    {
    lock (listLock)
    {
    // Delete an object from yourList
    // ...
    }
    }

    In summary, the behavior depends on how your code is structured and whether you've taken precautions to handle concurrent access to the list. If you anticipate multiple threads accessing and modifying the same list, consider using thread-safe collections or synchronization mechanisms to ensure consistent and safe behavior.


    codewars.com Rank: 4 kyu
    Vielleicht zeigst du mal ein bisschen Beispielcode zu deinen Beschreibungen, ich denke auch ChatGPT weiß nicht so recht wohin du willst, und gibt dementsprechend ein breitgefasstes Spektrum an Überlegungen zurück.

    Wenn du keins der besonderen Dinge tust, die der Bot erzeugt, dann beginnt jede Funktion dort wo sie im Code steht. Eventhandler die durch ein Event ausgelöst werden warten allerdings auf aktive Funktionen.
    @Haudruferzappeltnoch Ich fand die Antwort von Chat GPT eigentlich ganz gut:

    "
    ...
    Synchronization: By default, C# collections like List<T> are not thread-safe. If multiple threads are accessing and modifying the list concurrently, it can lead to issues like race conditions, exceptions, or unexpected behavior.
    ...
    "
    Beispielcode:
    Code ist nicht so einfach da Maui Hybrid Project -> Razorpages, C#, JavaScript, Html, Css und dann noch oben drauf JSRuntime damit JS und C# sprechen können. Hier wäre mal der c# Callback vom JavaScript Event (Js feuert in dem Moment wenn die Audiodatei im Html DOM fertig ist mit abspielen und gibt eine Guid.ToString() als ID zurück von dem T-Objekt das abgespielt wurde).

    C#-Quellcode

    1. ​ [JSInvokable]
    2. public async Task OnEnd(string id)
    3. {
    4. var res = GameState.GameActivTiles.Where(x => x.Id == id).FirstOrDefault();
    5. GameLogic.TileStateCheckStopped(res); // löscht obj aus Liste
    6. StateHasChanged(); // Blazor kram damit das UI refreshed wird
    7. }


    Mit der Id wird das Object aus der List<T> rausgesucht. Mit dem Objekt wird dann GameLogic.TileStateCheckStopped() aufgerufen und hier wird das Objekt dann aus der Liste gelöscht. Das alles passiert ohne Usereingabe.
    Aktiv kann der User jederzeit auf den Play Button drücken und dann wird das T-Objekt (inkl. Audiofiledateiname) abgespielt und das T-Objkt in die GameState.GameActivTiles geadded. Mehrere Playbuttons können nach einander gedrückt werden und die Audiodateien werden je nach länge zu unterschiedlichen Zeiten dann mit dem Event wieder gelöscht. Das Löschen passiert also für mich zu Zeitpunkten die ich nicht kenne. Je nachdem was der User abspielt.

    Und da war die Frage wartet das 'Löschen' Event auf die GameLogic.TileStateCheckPlay Funktion die ja auch die Liste-GameActivTiles 'bearbeitet'. Laut Chat GPT Antwort nein. Außer ich kümmere mich :) Das wie ich mich kümmern müsste (lock) hab ich jetzt noch nicht im Detail nachvollziehen können.

    ------------
    Falls das jetzt alles zu verwirrend rüberkommt:
    Eine Methode/Funktion ändert Properties von einem Objekt welches auch noch in einer Liste<T> referenziert ist. Zu einem 'willkürlichen' Zeitpunkt called ein JS-Event eine Funktion in C# die unteranderem Objekte aus der besagten List<T> löscht. Daher die Frage wie macht .net das mit der Reihenfolge?
    codewars.com Rank: 4 kyu
    ich kann dir nichts besonderes zur Threads, Locking, Maui oder JS erzählen. Aber vielleicht hilft es ja über das Konzept nachzudenken.

    nogood schrieb:

    Eine Methode/Funktion ändert Properties von einem Objekt welches auch noch in einer Liste<T> referenziert ist

    Also wenn das Objekt mehrfach referenziert ist, dann ändert das Löschen aus der Liste erstmal nix daran das Properties davon geändert werden können. Wann auch immer.
    Aus dem obigen Schrieb entnehme ich aber wohl, dass du diese Änderung auch über die Referenz aus der Liste erledigen willst?
    Und wenns dann eben schon gelöscht ist, muss ja nichts geändert werden, oder?

    Das mit der Reihenfolge ist auch klar, bei mehreren Threads gibt es keine, das ist doch der Sinn davon, dass die gleichzeitig laufen können.