genutzte Datei schliessen - Datei wird von anderem Prozess genutzt

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Snake3000.

    genutzte Datei schliessen - Datei wird von anderem Prozess genutzt

    Hallo Gemeinde,

    ich schlage mich seit mehreren Tagen mit einem Problemchen herum und brauche da mal Anregungen oder Hinweise.
    Alle eure Tipps in verwanten Themen habe ich durchexerziert, aber ich bin nicht sicher ob ich es nun richtig mache und mag keinen Geistern mehr hinterherjagen.

    Ich verwende eine jpeg Datei zur Anzeige in zwei PictureBoxen. Dazu habe ich ein Objekt deklariert
    Public seimg As Bitmap

    Beim starten meines Programmes instanziiere ich das mit
    seimg=New Bitmap(PictureBox1.Width, PictureBox1.Height)

    Bei der Verwendung weise ich die Datei zu
    seimg = Image.FromFile(datei)

    Soweit so gut. Jetzt kommt es dazu das ich diese Datei, samt des Verzeichnisses in dem sie liegt, von meinem Programm löschen mag.
    System.IO.Directory.Delete(pfad, True)

    Vorher sage ich aber noch
    seimg.Dispose() und auch
    PictureBox1.Image.Dispose()
    PictureBox2.Image.Dispose()

    Der Fehler "Datei wird von anderem Prozess verwendet" ist mir immer wieder mal über den Weg gelaufen während der Entwicklung.
    Jetzt mag ich es nicht wirklich dem weiter hinterher zu rennen.

    Meine Fragen sind nun, ist das so richtig? Reicht das? Was muss ich noch machen? Was mache ich falsch?

    Ich glaube zu verstehen das ich die Datei nutze, also Eigentümer bin, solange seimg damit verbunden ist und lebt. Ebenso natuerlich die beiden Picboxen.
    Reicht das .dispose dann aus um die Objekte von der Datei zu trennen?

    PS: Ich nutze jetzt mal die Möglichkeit euch allen vielmals zu danken für alle Einträge hier im Forum. Das hat mir schon viel genutzt in letzter Vergangenheit!


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Snake3000“ ()

    Snake3000 schrieb:

    VB.NET-Quellcode

    1. seimg = Image.FromFile(datei)
    Machma so was:

    VB.NET-Quellcode

    1. Dim seimg As Bitmap
    2. Using fs = New IO.FileStream("Datei", IO.FileMode.Open)
    3. seimg = New Bitmap(fs)
    4. ' bmp verwenden
    5. End Using
    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!
    Ich glaube die Idee dahinter zu verstehen, natürlich habe ich vergessen im original Post zu sagen das ich seimg auch mehrfach verwende, deswegen ist es ja auch global deklariert. Also zum Beispiel
    PictureBox1.Image = seimg

    Ich nutze es also an verschiedenen stellen nicht nur innerhalb eines Using/End Using.

    Aber trotzdem super Danke, Deine Antworten regen immer zum Denken an...
    @Snake3000 Dann hast Du wohl das ganze nicht richtig verstanden bzw. umgesetzt: ;)

    Quellcode

    1. Global Public Overall Usable seimg As Bitmap
    2. Using fs = New IO.FileStream("Datei", IO.FileMode.Open)
    3. seimg = New Bitmap(fs)
    4. End Using
    5. ' seimg global verwenden

    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!
    Da hast Du wohl recht, da habe ich so einiges offenbar noch nicht richtig verstanden....

    Trotzdem habe ich noch immer die selbe Frage.

    Womit löse ich die Bindung meines Programmes zu einer Datei???

    Tut es das .Dispose ??????

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Snake3000“ ()

    Rod, ich danke Dir....

    Das scheint es tatsächlich zu tun. Ich hoffe es nun auch verstanden zu haben......

    Ich bin begeistert!!!

    edit: Leider wurde die Begeisterung gerade gedämpft.
    Nun laufe ich in eine System.OutOfMemoryException: "Nicht genügend Arbeitsspeicher."
    wenn ich nach
    Dim sezoom As Bitmap
    sezoom = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    das sage
    sezoom = seimg.Clone(New Rectangle(0, seimg.Height / 2, (seimg.Width / 2), (seimg.Height / 2)), Imaging.PixelFormat.DontCare)

    hmmmmm….. mit dem ursprünglichem Aufruf
    seimg = Image.FromFile(Datei)
    hat das funktioniert.

    Jetzt bin ich erneut Ratlos

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

    Hi!

    Ich denke Du musst wenn Du die Bitmap "clonen" willst nicht extra eine "New Bitmap" erzeugen..
    ..es reicht, denk ich, wenn Du

    VB.NET-Quellcode

    1. Dim sezoom As Bitmap = seimg.Clone(New Rectangle(0, seimg.Height / 2, (seimg.Width / 2), (seimg.Height / 2)), Imaging.PixelFormat.DontCare)


    schreibst!

    Oder Du guckst Dir mal "BitBlt" an! ;)
    codeproject.com/Articles/6710/…o-Copy-and-Paste-Graphics

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Morrison“ ()

    Snake3000 schrieb:

    "Nicht genügend Arbeitsspeicher."
    Da fällt mir im Moment nur x64 ein.
    Was hast Du für einen Rechner, was für ein Betriebssystem, wie wird Dein Programm compiliert (x86, x64, AnyCPU)?
    Kann es sein, dass Du das Bild beliebig oft clonst und dann nicht wieder beräumst?
    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!
    Die beste Art Bitmaps zu Klonen finde ich so. Man kriegt so auch keine Meldung, so von wegen Datei wird vom Prozess verwendet.

    VB.NET-Quellcode

    1. Private Function GetImageClone(bm As Bitmap) As Bitmap
    2. Using bmclone = New Bitmap(bm.Width, bm.Height, PixelFormat.Format32bppPArgb)
    3. Using g = Graphics.FromImage(bmclone)
    4. Dim res As New Bitmap(bm)
    5. g.DrawImage(res, New Rectangle(0, 0, bmclone.Width, bmclone.Height))
    6. Return res
    7. End Using
    8. End Using
    9. End Function


    Aufgerufen werden kann es z.B. so

    VB.NET-Quellcode

    1. dim mypic as Bitmap 'Oder Klassenübergreifend deklarieren
    2. Using pic = New Bitmap(picname, True)
    3. mypic = GetImageClone(pic)
    4. End Using


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    hmm - du erstellst da 2 Bitmapse, um nur einen Klon zu erzeugen? Dassis iwie schwer uncool.
    Ich würd lieber bei der vom Framework gegebenen Klon-Methode bleiben, und vlt. annere PixelFormats ausprobieren, als das PixelFormat.Scheissegal.
    Auch genau debuggen, unter welchen Randbedingugen der Fehler kommt: vlt. liegt Höhe oder Breite 0 vor, oder vlt. ists ein ganz bestimmtes Bild-Datei, bei ders failt - Bild-Dateien sind immer mal für Überraschungen gut.
    Ich weiss, sieht irgendwie nicht professionell aus.

    Ich hatte mal ein Problem, wo die Klon-Methode vom Framwork immer versagt hatte.
    Damals musste ich das Bitmap auch wieder abspeichern, mit dem gleichen Namen. Es wollte einfach nicht funktionieren, egal was ich gemacht habe. Die Meldung (Bitmap wird vom Prozess verwendet … ) kam während der Manipulation des Bildes, oder beim neu abspeichern. Mit meiner oben erwähnten Funktion hat es dann endlich geklappt.

    Eine weitere Möglichkeit wäre wahrscheinlich noch das Serialisieren um einen sauberen Klon zu machen.

    Freundliche Grüsse

    exc-jdbi

    EDIT: Danke EDR. Funktioniert soweit. Starker Konverter der ImageConverter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    ich kannte das mit klonen garnet. Jo, wenn der Klon genauso eine Sperre auf die Datei hält, wie die original-Bitmap, dann ist diese Art zu klonen natürlich total unzweckmäßig für den hier beabsichtigten Zweck.
    Ich hab gute Erfahrung mitte ImageConverter-Klasse gemacht:

    VB.NET-Quellcode

    1. Private Shared _ImgConv As New ImageConverter
    2. Public Shared Function LoadBitmap(filePath$) As Bitmap
    3. Return DirectCast(_ImgConv.ConvertFrom(File.ReadAllBytes(filePath)), Bitmap)
    4. End Function
    Bin ich drauf gekommen, weil Databinding intern auch damit arbeitet.
    Vielen Dank für all eure Vorschläge, nun meine Rückmeldung nachdem ich wieder Zeit hatte zu fummeln.

    Mein ursprüngliches Problem mit der verwendeten Datei scheint mit Rods Tip gelöst zu sein. Da bin ich zuversichtlich.

    Das danach aufgetretene Problem, des nicht genügenden Arbeitsspeichers im Schritt des clonens, konnte offenbar mit exc-jdbi s Methode eliminiert werden.

    Auf jedenfall treten beide Fehler, so wie ich es getestet habe, nicht mehr auf. Ich muss aber noch weitertesten, auch mit anderen Bildern. Zum einen wegen des Erfinders Rat (vielen Dank dafür) und auch wegen der jetztigen Verwendung des Pixelformates "Format32bppPArgb", denn das hinterläst mich ratlos.

    Im übrigen kompiliere ich mit "any CPU" im VS2017 mit dem Framework 4.7. unter Window10 64bit auf einem I3-600 2Ghz mit 8GB RAM... puh :)
    Was war der Verdacht? Muss ich da an was besonderes denken?
    Rods Tip ist aber glaub unsicher.
    Eine Bitmap behält ja eine Verbindung mit dem FileStream, aus dem sie erstellt wird. Wenn dieser aber disposed ist so befinden sich die Bitmap-Daten GarbageCollectormässig in einem undefinierten Zustand.
    Ich meine mich zu erinnern, mit dergleichen schon unerfreuliche Überaschungen erlebt zu haben - kann ich aber grad nicht mehr belegen.

    ErfinderDesRades schrieb:

    Rods Tip ist aber glaub unsicher.
    Nö, der wird sogar von Microsoft propagiert, glaub ich.
    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!
    Also für mich schauts im Moment gut aus.
    Ich konnte in den Fehler mit meiner Version reproduzierbar hineinlaufen, habe dann lediglich zu Rods Weg gewechselt und der Fehler ist nicht mehr aufgetreten.
    Daher würde ich die Frage erstmal als beantwortet einstufen.
    Sollten mir auf dem weiteren Weg noch Unregelmässigkeiten auffallen sage ich gerne Bescheid.

    Also auf jeden Fall herzlichen Dank an Euch Alle.