GDI Zeichenfehler anzeigen

  • VB.NET
  • .NET (FX) 4.0

Es gibt 47 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Müssen nicht, allerdingst ist dies für das Aussehen sehr vorteilhaft. Dennoch verstehe ich es nicht ganz. Sie werden doch direkt danach disposed?
    Bezüglich GC.Collect Ich hatte es nach der For Schleife. Leider ohne erfolgt..
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    GC.Collect soll man garnicht aufrufen.
    Das bringt nur den Collecting-Algo durcheinander - besser wird dadurch bestimmt nichts.
    (also ich habs nicht geprüft, ich gebe hier nur wieder, wass ich an verschiedenen Stellen im Inet aufgeschnappt hab, und was mir plausibel erschien - aber die Stellen kann ich jetzt auch nicht mehr angeben)

    Gather schrieb:

    Sie werden doch direkt danach disposed?
    Klar werden sie disposed, trotzdem fressen sie viel Speicher. Vielleicht lässt sich das doch durch Vorabberechnung erledigen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dispose zerstört nur die zugrundeliegenden GDI objekte, welche mittels WinAPI erzeugt werden, nicht jedoch die .Net Wrapper Objekte, die sollten irgendwann vom GC aufgeräumt werden, die Frage ist allerdings warum das nicht passiert. Hast du die Diagnosesitzung mal bis zum Ende durchlaufen lassen? Vlt. auch ein paar Snapshots machen, sodass man eine Steigerung von bestimmten Objekten sieht. Denn eigt. sollten die LinearGradientBrush spätestens aufgeräumt werden, wenn der Speicher ausgeht.

    Es sieht aber auch so aus, als könnte man die Brushes poolen, wäre vlt. auch eine Idee, falls die tatsächlich schuld sind.

    Edit: GC.Collect sollte man tatsächlich selten verwenden, heißt aber nicht, dass man es gar nicht verwenden soll, manchmal ist der Programmierer schlauer als der GC und weiß wann aufgeräumt werden darf und wann nicht. Nur sollte das bei Business Anwendungen so gut wie nie der Fall sein. Wenn es um Grafikrendering geht aber schon eher.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    jvbsl schrieb:

    Denn eigt. sollten die LinearGradientBrush spätestens aufgeräumt werden, wenn der Speicher ausgeht.
    Das ist korrekt. Passiert auch (denke ich), wenn man das Ganze ebenfalls durch ein TryCatch laufen lässt, flackert es lediglich eine Millisekunde wenn der Speicher voll ist. Das Kreuz kann damit also vermieden werden, allerdings ist das mit dem TryCatch nicht der schönste Weg.

    Edit://
    Bezüglich der DiagnoseSitzung und den Snapshots. Wie genau funktioniert das? Ich habe bisher noch nie dieses Feature verwendet :(

    Edit:// Problem ist auch, dass man bei Drawing2D.LinearGradientBrush die Punkte, nach dem Erstellen, nicht mehr verändern kann.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


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

    @Gather Wie schnell hintereinander wird denn diese Prozedur aufgerufen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany: Grundsätzlich ca alle 50ms. ALLERDINGS tut dies nicht zur Sache. Denn in Tests hat sich gezeigt, dass selbst wenn die Prozedur nur jede halbe oder gar ganze Sekunde aufgerufen wird,
    es früher oder später auch zu dem Fehler "Nicht genügend Arbeitsspeicher vorhanden." kommt. Mit 50ms passiert dies ganz einfach nur schneller... :/
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Tja, dann fällt mir fürs Pooling nur ein:
    referencesource.microsoft.com/…ed/LinearGradientBrush.cs
    Entweder das komplette Teil schnappen und neu bauen, oder eben
    mittels Reflection "void SetNativeBrushInternal(IntPtr brush)" auf zu rufen um die Objekte zu switchen und eben nur die GDI handles erzeugen/zu löschen indem du die Konstruktoren extra implementierst^^

    Aber kommt mir alles unschön vor, hört sich irgendwie nach einem Bug an das ganze
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Es gibt also kurz und knapp keine möglichkeit die punkte in einem lineargradientbrush zu verändern?
    Das Einzige was ich jetzt auf die schnelle gesehen hätte wäre die .Blend Property, aber ich kann mir nicht vorstellen wie ich zwei Punkte in Single konvertieren könnte.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Gather schrieb:

    die punkte in einem lineargradientbrush zu verändern
    Ich gehe mal davon aus, dass es nicht geht, weil das intern ein unmanaged Objekt ist, weshalb auch der Speicher zuläuft.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Gut, das heißt bis auf vorläufiges erstellen der Elemente, ist es also nicht zu beheben..
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Gather schrieb:

    Das ist korrekt. Passiert auch (denke ich), wenn man das Ganze ebenfalls durch ein TryCatch laufen lässt, flackert es lediglich eine Millisekunde wenn der Speicher voll ist. Das Kreuz kann damit also vermieden werden, allerdings ist das mit dem TryCatch nicht der schönste Weg.
    um es in mein Deutsch zu übersetzen: Wenn man "das Ganze" (was immer das sein mag - vermutlich der Inhalt der Zeichen-Methode) in einen TryCatch packt, dann läuft die Anwendung.
    D.h.: Der Fehler tritt nachwievor auf, kann aber übergangen werden ohne Folgefehler (flackert dann nur bischen).
    richtig?

    Gather schrieb:

    Grundsätzlich ca alle 50ms. ALLERDINGS tut dies nicht zur Sache...
    Da bin ich immer bass erstaunt, wenn Leuts einen Fehler zwar nicht beheben können, aber ganz genau zu wissen meinen, was was zur Sache tut und was nicht.

    Mich jdfs. würde jetzt brennend interessieren, wie du die Zeichenroutine aufrufst.
    Ich glaub nicht, das dass n Bug ist. Referencesource sieht ja auch erstmal i.O. aus. Aufgeräumt wird in der Basisklasse Brush, also müsste es bei allen Brushes sein. Ich weiß auch nicht wie genau es intrrn in GDI+ läuft, die C++ Objekte muss man z.B. nicht aufräumen, wird alles normal im Destruktor gemacht. Kannst du denn kein Testprojekt hochladen? Würde mich nämlich auch interessieren. Hast du denn die LinearGradientBrush einfach mal auskommentiert und erneut getestet? Btw bist du dir sicher, dass man die Punkte nicht nicht ändern kann? Glaube das ging über die Blend. Speichermäßig alle 50ms eine neue Brush erzeugen ist ja erstmal egal, aber für die Performance natürlich Katastrophe.

    ErfinderDesRades schrieb:

    richtig?

    Das ist korrekt.

    Zusätzlich sieht die Zeichenmethode 1zu1 aus wie oben angeben. Aufgerufen wird es simpel mit Invalidate(), via Timer.
    Und ja das Problem Tritt auf wenn der Timer auf 50ms ist, sowie wenn er auf 1000 ist.

    Edit:// Demoprojekt folgt.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


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

    Hey, ich habe festgestellt das die OutOfMemoryException dann auftritt wenn p.Location die gleichen koordinaten wie possiblePoint.Location hat. So läuft es anständig durch.

    VB.NET-Quellcode

    1. Public Sub DrawGalaxy(g As Graphics, points As BoundPoint(), _
    2. Optional connectionDistance As Integer = 50, _
    3. Optional lineAlpha As Integer = 50, _
    4. Optional useOverlayColor As Boolean = False)
    5. g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
    6. If points.Length >= 1 Then
    7. ' Try
    8. Dim b As New SolidBrush(_OverlayColor)
    9. For Each p In points
    10. For Each possiblePoint In points
    11. If possiblePoint IsNot p Then
    12. Dim d As Double = MeasurePointDistance(p.Location, possiblePoint.Location)
    13. If d < connectionDistance Then
    14. If p.Color.A < lineAlpha Then lineAlpha = p.Color.A
    15. Dim lgb As LinearGradientBrush = Nothing
    16. If p.Location <> possiblePoint.Location Then
    17. lgb = New LinearGradientBrush(p.Location, possiblePoint.Location, Color.FromArgb(lineAlpha, p.Color), Color.FromArgb(lineAlpha, possiblePoint.Color))
    18. Using Pen As New Pen(lgb)
    19. g.DrawLine(Pen, p.Location, possiblePoint.Location)
    20. End Using
    21. End If
    22. If lgb IsNot Nothing Then
    23. lgb.Dispose()
    24. End If
    25. End If
    26. End If
    27. Next
    28. b.Color = If(useOverlayColor, _OverlayColor, p.Color)
    29. g.FillEllipse(b, New Rectangle(p.Location.X - CInt(p.Width / 2), p.Location.Y - CInt(p.Width / 2), p.Width, p.Width))
    30. Next
    31. b.Dispose()
    32. ' Catch ex As Exception
    33. ' Im Normalfall nur ausgelöst wenn Arbeitsspeicher voll.
    34. ' End Try
    35. End If
    36. End Sub
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    @NoIde
    Wow. Faszinierend, es funktioniert.!
    Wobei ich zugeben muss, dass mir nicht klar ist wieso...

    Funktioniert sogar mit mehreren hundert Punkten, sowie einem Intervall von 30ms.

    Edit://
    Oh verstehe. Danke für deine Hilfe!
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Gerne doch. Tipp für das nächste mal, in dem ich erkläre wie ich das fand. Ich habe erstmal den Try/Catch rauskommentiert, in der Zeile in der du den LinearGradientBrush erstellt hast, kam es zu der Exception, im wieder rein kommentierten Try/Catch habe ich mir dann einfach mal die Variablen im Catch angeschaut, welche du zur erzeugung nutzt, so konnte ich die identischen Koordinaten als Ursache erkennen.
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

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