"Nicht genügend Arbeitsspeicher"

  • VB.NET

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von vivil.

    "Nicht genügend Arbeitsspeicher"

    Hallo Forum,

    ich habe da mal wieder eine Frage.

    Und zwar handelt es sich darum, dass ich große Bilder (11694 x 8264 Pixel) als Hintergrund eines Panels anzeigen will.
    Dies funktioniert auch beim ersten klick, nur danach (also beim zweiten klick) kommt die Fehlermeldung:
    System.OutOfMemoryException: Nicht genügend Arbeitsspeicher.
    bei System.Drawing.Graphics.CheckErrorStatus(Int32 status)
    bei System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
    bei System.Drawing.Bitmap..ctor(Image original, Int32 width, Int32 height)
    bei System.Drawing.Bitmap..ctor(Image original)
    bei VS.VS.objekt.loadMaps(Int32 idmap, Boolean newmap) in C:\csvn\VS2010\VS\objekt.vb:Zeile 1435.
    bei VS.VS.objekt.loadMap(Int32 _idmap, Boolean newmap) in C:\csvn\VS2010\VS\objekt.vb:Zeile 574.
    bei VS.VS.objekt.objekt_Load(Object sender, EventArgs e) in C:\csvn\VS2010\VS\objekt.vb:Zeile 310.
    bei System.Windows.Forms.Form.OnLoad(EventArgs e)
    bei System.Windows.Forms.Form.OnCreateControl()
    bei System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
    bei System.Windows.Forms.Control.CreateControl()
    bei System.Windows.Forms.Control.WmShowWindow(Message& m)
    bei System.Windows.Forms.Control.WndProc(Message& m)
    bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
    bei System.Windows.Forms.Form.WmShowWindow(Message& m)
    bei System.Windows.Forms.Form.WndProc(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    Jetzt ist das Problem, dass bevor ich das Bild dem Panel zuweise, der Arbeitsspeicher geleert wird.
    Woran kann das denn jetzt liegen, dass diese Meldung immer noch kommt ?

    Code:

    VB.NET-Quellcode

    1. Dim findmap() As DataRow
    2. findmap = tamaps.Select("idmap = " & idmap)
    3. Dim mapname As String = findmap(0).Item(1)
    4. Dim mapimage As Bitmap = Nothing
    5. Using fs = New FileStream("maps" & mapname, FileMode.Open)
    6. Using original As Image = Image.FromStream(fs)
    7. mapimage = New Bitmap(original)
    8. fs.Close()
    9. original.Dispose()
    10. End Using
    11. End Using


    Würde mich sehr um Antworten freuen.


    vivil
    @sonne75

    Meines Wissens (!) nach ist es in Zeile 1 und 8 nicht nötig, da es ja kein 'Neues' XY sein soll, sondern vom Typ XY und bekommt dann ja den Wert von einem bestehenden Object des Typs XY.

    In Zeile 4 ist es gängiger Dim mapimage As New Bitmap(w, h) zu schreiben, als Dim mapimage As Bitmap = Nothing.
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais

    Arby schrieb:

    Hm... langen Tag gehabt?

    Nein, zu häufig Fehler wegen fehlendem New gehabt und deswegen etwas sensibilisiert darauf. Zumal es sehr sehr häufig immer noch solche Fehler hier im Forum auftauchen, also hätte es ja sein können.

    Aber es klingt logisch, New erstellt eine leere Instanz, ohne New nur eine Referenz. Wenn man also eine Referenz auf etwas setzt (mit =), dann braucht man diese leere Instanz also nicht.

    Aber es war immerhin ein Ansatz, auch wenn ein falscher. ;) Ich lerne auch am besten aus Fehlern...

    EDIT: habe ja schon eingesehen. Ich will hier auch lernen. ;)
    Wenn du nur schreibst

    VB.NET-Quellcode

    1. Dim b as Bitmap


    Hast du der Variable b nur den Typ Bitmap mitgegeben. Hier kannst du nur auf die statischen Member zugreifen (Es existiert keine Instanz -> nix im Arbeitsspeicher (Managed Heap)). Machst du dann jedoch

    VB.NET-Quellcode

    1. b = new Bitmap

    Existiert eine Instanz davon.
    Mögliche wäre nun auch das:

    VB.NET-Quellcode

    1. Dim c as Bitmap = b

    Es wird keine neue Instanz erzeugt, sondern nur der Zeiger kopiert (b und c zeigen nun auf das selbe).

    Gleiches passiert bei

    VB.NET-Quellcode

    1. Dim findmap() As DataRow
    2. findmap = tamaps.Select("idmap = " & idmap)


    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Eigentlich an alle. Jedoch find ich den Begriff "leere Instanz" etwas irreführend. Denn sobald New im Spiel ist eine Instanz (welche nach New ja auch gleich (Standard-)Werte beinhalten kann. Deswegen find ich da leer nicht so passend) vorhanden. Referenz find ich auch verwirrend da man in .Net ja auch von "Referenztypen" (Klassen) spricht. Bei Referenz versteh ich darunter einen Zeiger auf eine Speicheradresse (was aber ja dann wieder genau verkehrt rum ist -> "ohne New nur eine Referenz").

    Vermutlich hast du das selbe gemeint, die Wortwahl war für mich aber irreführend ;)

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Da war doch was mit Stack und Heap oder? Auf dem Stack liegen Referenzen auf die Daten (Objekt), die in Heap liegen? (Kann auch umgekehrt gewesen sein, ich kann es mir nie merken :whistling: ).
    Ohne New ist da nur ein "Zeiger" in dem Sinne, dass er auf keine Daten (Objekt) zeigt. Mit New werden auch Daten (und wenn es nur "Nothing" ist) erzeugt, sprich, Speicherbereich im Heap (??), auf die dann der Zeiger (der Variablenname) zeigt. Wenn man also ohne "New" auf die Daten zugreifen will, gibt es eine Exception, dass es kein Objekt gibt.
    Wenn man nur den Typ deklariert (ohne New) und dann mit "=" dem Speicherbereich (den Daten) zuweist, dann ist wieder alles gut, weil das Programm weiß, auf welche Daten es beim Aufruf zugreifen soll. Es existieren quasi 2 "Zeiger", der urprüngliche und der Neue.

    Ich hoffe, es war jetzt richtig.

    ErfinderDesRades schrieb:


    eine Bitmap muss man disposen, wenn man sie nicht mehr braucht.
    Bevor du also eine neue Bitmap erzeugst, erstmal bei der alten, die ja noch im Panel angezeigt wird, Bitmap.Dispose aufrufen.

    vlt. hilfts ja.
    Das mache ich bevor das Bild geladen wird.
    Da schaue ich nach, ob mein mapimage gefüllt ist oder nicht, wenn gefüllt, dann dispose.


    Es wird keine neue Instanz erzeugt, sondern nur der Zeiger kopiert (b und c zeigen nun auf das selbe).


    Vielleicht liegt es daran, wie soll ich dies deiner Meinung nach lösen ?
    Im Stack liegt alles im Heap sind Referenzen auf Dinge im Stack <- hatte wir erst vor kurzem in der Berufschule
    Ich Antworte nach bestem Wissen und Gewissen. Ich übernehme keine Garantie für die Richtigkeit oder Fehlerfreiheit meiner Texte.


    Ich konnte dir helfen?
    - Das ist schön :) Ich würde mich über ein "Hilfreich" freuen ^^
    Auf dem (Prozessor-) Stack werden Structures (Integer, Date, ...) abgelegt, da man darauf schneller zugreifen kann als wie auf den Arbeitsspeicher.
    Ohne New gibt es keinen Zeiger. Da ist einfach nur der Variablentyp deklariert. Würde man

    VB.NET-Quellcode

    1. Dim b as New Bitmap
    2. b = Nothing

    machen, bin ich mir nicht ganz sicher, ich meine aber, dass das Objekt dann verworfen wird. Mit New wird im Grunde nichts anderes gemacht als das im Arbeitsspeicher (Managed Heap) ein Platz dafür reserviert wird. Somit hat man ein Objekt erzeugt.
    Bei dem Beispiel:

    VB.NET-Quellcode

    1. Dim b as New Bitmap
    2. Dim c as Bitmap = b

    existiert nur 1 Speicherbereich (Objekt). Man hat 2 Objektvariablen die aber beide die gleiche Zeigeradresse haben (1 Zeiger)

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    @sonne75: Dann hat unser Lehrer uns 'nen Scheiß erzählt...
    Ich Antworte nach bestem Wissen und Gewissen. Ich übernehme keine Garantie für die Richtigkeit oder Fehlerfreiheit meiner Texte.


    Ich konnte dir helfen?
    - Das ist schön :) Ich würde mich über ein "Hilfreich" freuen ^^