Doppelte Ausführung von OnInitializedAsync und Dispose in MudBlazor beim Anzeigen von Bildern

  • C# (ASP)

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.

    Doppelte Ausführung von OnInitializedAsync und Dispose in MudBlazor beim Anzeigen von Bildern

    Hallo zusammen,

    ich möchte eine Website mit MudBlazor und C#.NET 9 erstellen. Auf einer der Seiten möchte ich Bilder anzeigen, die im Eventhandler OnInitializedAsync geladen werden. Um den Fall abzudecken, dass der Benutzer die Seite verlässt, habe ich eine Dispose-Methode implementiert.

    Allerdings habe ich festgestellt, dass sowohl OnInitializedAsync als auch Dispose zweimal ausgeführt werden.

    Konsolenausgabe:
    OnInitializedAsync executed.
    Dispose executed.
    OnInitializedAsync executed.
    Dispose executed.


    Dieses Verhalten tritt nur auf, wenn Bilder angezeigt werden.

    Ich frage mich, warum das passiert und wie ich unnötige Festplattenzugriffe (oder spätere Datenbankzugriffe) verhindern kann.

    Ich habe bereits versucht, ein auf true gesetztes Flag _isInitialized zu verwenden, um ein zweites Dispose zu verhindern, aber Dispose wird trotzdem zweimal aufgerufen.
    Ich habe auch versucht, OnAfterRenderAsync mit dem Flag _isRendered zu verwenden, aber da OnAfterRenderAsync mehrmals ausgelöst wird, ist es nicht geeignet, da die Bilder zu oft neu geladen werden.

    Ich habe ein minimales, ausführbares Beispiel zur Überprüfung bereitgestellt.

    Nachtrag: Auch, wenn 2× die Dispose-Methode aufgerufen wird, bleiben die Bilder sichtbar.

    C#-Quellcode

    1. namespace BlazorMinimalExample2
    2. {
    3. public class Foo
    4. {
    5. public byte[]? ImageAsByteArray { get; set; }
    6. public Foo(byte[] stuff)
    7. {
    8. this.ImageAsByteArray = stuff;
    9. }
    10. public void CleanUp()
    11. {
    12. if (this.ImageAsByteArray != null)
    13. {
    14. this.ImageAsByteArray = null;
    15. }
    16. }
    17. }
    18. }


    Razor-Seite:
    Spoiler anzeigen

    Quellcode

    1. @page "/"
    2. @using MudBlazor
    3. @implements IDisposable
    4. @inject NavigationManager Navigation
    5. <MudLayout>
    6. @if (Foos.Count > 0)
    7. {
    8. <MudGrid Class="mt-4" Spacing="0">
    9. @foreach (Foo f in Foos)
    10. {
    11. @if (f.ImageAsByteArray != null)
    12. {
    13. <MudItem xs="12" sm="6" md="4">
    14. <MudCardContent Dense="true">
    15. <MudImage Src="@($"data:image;base64,{Convert.ToBase64String(f.ImageAsByteArray)}")" Elevation="25" Class="rounded-lg ma-2 d-block mx-auto" Width="350" Height="350" />
    16. </MudCardContent>
    17. </MudItem>
    18. }
    19. }
    20. </MudGrid>
    21. }
    22. </MudLayout>
    23. @code {
    24. private List<Foo> Foos = new List<Foo>();
    25. protected override async Task OnInitializedAsync()
    26. {
    27. Foos = await LoadImages();
    28. Console.WriteLine("OnInitializedAsync executed.");
    29. }
    30. public void Dispose()
    31. {
    32. Console.WriteLine("Dispose executed.");
    33. foreach (Foo foo in Foos)
    34. {
    35. foo.CleanUp();
    36. }
    37. }
    38. private Task<List<Foo>> LoadImages()
    39. {
    40. List<Foo> foos = new List<Foo>();
    41. Foo foo1 = new Foo(System.IO.File.ReadAllBytes(@$"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\Pictures\20190119_131055 2.jpg"));
    42. foos.Add(foo1);
    43. Foo foo2 = new Foo(System.IO.File.ReadAllBytes(@$"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\Pictures\20210117_010401.jpg"));
    44. foos.Add(foo2);
    45. return Task.FromResult(foos);
    46. }
    47. }

    *Topic verschoben*

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Bartosz“ ()

    Hallo @wolfi_bayern,
    danke für den Link. Ich habe festgestellt, dass ich in meinem Mudblazor-Projekt keine _Host.cshtml habe. Ich habe nun, basierend auf null, @rendermode @(new InteractiveServerRenderMode(prerender:false)) geschrieben. Das bewirkt aber auch nur, dass das zweite Dispose nicht aufgerufen wird (sondern erst beim Verlassen der Seite), aber nicht wie gewünscht, dass die Daten nicht zweimal geholt werden.

    Edit: Auf einer anderen Seite, auf der ich jetzt auch @rendermode @(new InteractiveServerRenderMode(prerender:false)) benutze, werden Daten nur einmal geholt – OnInitializedAsync wird nur einmal aufgerufen. Auf der Seite werden keine Bilder dargestellt, aber eine Suche wird betätigt. Vorher wurde OnInitializedAsync auch 2× aufgerufen.

    Viele Grüße
    Bartosz

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Bartosz“ ()

    @wolfi_bayern Was meinst du mit Template? In Visual Studio stellte ich beim Projekterstellen Mudblazor ein. Bei der Auswahl, welcher Typ, stellte ich Server ein.
    MudBlazor war dann von Beginn an als Nuget-Paket installiert.
    Bilder
    • Screenshot 2025-03-09 181900.png

      13,37 kB, 526×243, 13 mal angesehen
    • Screenshot 2025-03-09 181923.png

      18,24 kB, 574×368, 15 mal angesehen

    Neu

    Genau! Um den Thread hier erfolgreich zu beenden:
    Man muss in die App.razor dies hier schreiben, um das Problem mit dem doppelten Laden zu zu lösen:
    @rendermode @(new InteractiveServerRenderMode(prerender:false))

    Die Seite, die die Bilder anzeigt, ist bei mir auch die, die beim Start der Anwendung angezeigt wird. Diese wird immer noch beim Start zwei Mal geladen. Danach aber nicht mehr, also beim Vor- und Zurücknavigieren.