PicturBox-ban használt File lezárása .

PicturBox-ban használt File lezárása .
2012-09-13T18:32:10+02:00
2012-09-15T09:42:39+02:00
2022-11-26T21:10:35+01:00
b_atti
Tudnátok-e segíteni. Az alábbi program a Bezáráskor pontosabban File törlésekor azt a hibát dobja hogy használatban van a File nem lehet hozzáférni. Köszi.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace FotoWiewer { public partial class Form1 : Form { string modFileName; public Form1(string FotoName) { InitializeComponent(); if (FotoName != "") { using (FileStream fs = new FileStream(FotoName, FileMode.Open, FileAccess.Read)) { PictureBox1.Image = Image.FromStream(fs); fs.Close(); } modFileName = FotoName; } } private void BezarGomb_Click(object sender, EventArgs e) { //PictureBox1.Image = null; File.Delete(modFileName); this.Close(); } } }
Mutasd a teljes hozzászólást!
Igen, úgy tűnik, ez bizony így működik. A PictureBox referenciája feltehetően közvetlenül mutat a stream-re, így azt nem törölheted, amíg használatban van.

Megoldás: másolat készítése memóriába, és akkor törölheted az eredetit.

Például így (monitor javaslata is alkalmazva lett, de rendes hibakezelés nincs benne):

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace PictureBoxTest { public partial class Form1 : Form { private string modFileName; private MemoryStream image = new MemoryStream(); public Form1(string FotoName) { InitializeComponent(); if (File.Exists(FotoName)) { using (Image img = Image.FromFile(FotoName)) { // veszteségmentes tömörítés img.Save(image, ImageFormat.Png); } PictureBox1.Image = Image.FromStream(image); modFileName = FotoName; } } private void BezarGomb_Click(object sender, EventArgs e) { File.Delete(modFileName); } } }
Mutasd a teljes hozzászólást!

  • A using, vagy Dispose() használata erősen javallot file műveleteknél.
    Mutasd a teljes hozzászólást!
  • Szerintem ezzel a kóddal nincs különösebb gond.
    Ez helyett:
    if (FotoName != "")
    viszont inkább így csinálnám:
    if (file.exists(FotoName))

    Nem használod a programod másik részén a fájlt, és azt nem szabadítod fel? Esetleg egy másik program?
    Mutasd a teljes hozzászólást!
  • Igen, úgy tűnik, ez bizony így működik. A PictureBox referenciája feltehetően közvetlenül mutat a stream-re, így azt nem törölheted, amíg használatban van.

    Megoldás: másolat készítése memóriába, és akkor törölheted az eredetit.

    Például így (monitor javaslata is alkalmazva lett, de rendes hibakezelés nincs benne):

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace PictureBoxTest { public partial class Form1 : Form { private string modFileName; private MemoryStream image = new MemoryStream(); public Form1(string FotoName) { InitializeComponent(); if (File.Exists(FotoName)) { using (Image img = Image.FromFile(FotoName)) { // veszteségmentes tömörítés img.Save(image, ImageFormat.Png); } PictureBox1.Image = Image.FromStream(image); modFileName = FotoName; } } private void BezarGomb_Click(object sender, EventArgs e) { File.Delete(modFileName); } } }
    Mutasd a teljes hozzászólást!
  • Köszi a válaszotokért.
    Máshol nem használom. Csak egy Form az egész. A program többi része:
    using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.IO; namespace FotoWiewer { static class Program { [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1(args[0])); } } }
    Csak egy bejövő file névvel dolgozik.
    A using-ot azért használtam, hogy biztos lezáródjon a file.
    De a program bezárásáig más alkalmazás sem tud semmit sem csinálni a file-al.
    Mutasd a teljes hozzászólást!
  • Mondjuk nekem úgy is sikerült a törlés, hogy közben egy képnézegetővel meg volt nyitva az adott fájl.

    Esetleg a FileShare-t is ha beállítod ?
    FileShare Enumeration (System.IO)

    pl:
    FileStream fs = new FileStream(FotoName, FileMode.Open, FileAccess.Read, FileShare.Read);
    Mutasd a teljes hozzászólást!
  • Észrevetted, hogy leírtam, mi a probléma és dobtam neked egy kész megoldást vagy csak
    szórom a gyöngyöket
    (megint)?
    Mutasd a teljes hozzászólást!
  • Észrevetted, hogy leírtam

    Szvsz észrevehette, csak később.
    Három perc van az írásotok között..
    Mutasd a teljes hozzászólást!
  • Bocsi! Én nem láttam a válaszodat mikor írtam.
    A te megoldásod fogadom el mert sokat tanultam belőle.
    A problémát a képelérést küldő program okozta nevezetesen a Thunderbird az fogta a képet, nem az én progim. Ezt pedig először ki is próbáltam, de akkor elnéztem valamit.
    Ha simán így nyitom meg a file-t akkor is törölhető.
    PictureBox1.Load(FotoName);
    Köszönöm mindenki hozzászólását!
    Mutasd a teljes hozzászólást!
  • A te megoldásod fogadom el mert sokat tanultam belőle.
    A problémát a képelérést küldő program okozta nevezetesen a Thunderbird az fogta a képet, nem az én progim.


    Viszont még monitor írta:
    Esetleg egy másik program?



    Persze minden tiszteletem Kukipapáé, én is sokat tanulok tőle, szeretem a hasznos példáit.
    Mutasd a teljes hozzászólást!
  • A PictureBox referenciája feltehetően közvetlenül mutat a stream-re, így azt nem törölheted, amíg használatban van.


    Ez szerintem nem így van, mert akkor a következő kód 2 buttonnal és 2 picturebox-al:
    1: miért nem ugyanazt a képet tartalmazza, a button1-re kattintásnál, ha ugyanarra a referenciára mutatnak?
    2: a button1-re történő többszöri kattintásnál miért engedi egyáltalán megnyitni bármelyik fájlt, ha a image fogva tartja?
    3: miért lehet törölni mind a 2 fájlt a button2-vel?

    Ráadásul olvasásra és írásra is megnyitom a fájlokat(FileAccess.ReadWrite).

    using System; using System.Drawing; using System.IO; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { string[] str = new string[] { @"Zöldkő.bmp", @"Zapoték.bmp" }; public Form1() { InitializeComponent(); //buttonok felülre button1.Top = 0; button2.Top = button1.Top; button2.Left = button1.Right + 10; //picture-ok a button alatt pictureBox1.Top = button1.Bottom + 10; pictureBox2.Top = pictureBox1.Top; button1_Click(new object(), new EventArgs()); pictureBox1.Left = 0; this.Width = pictureBox2.Right + 10; if (pictureBox1.Height > pictureBox2.Height) { this.Height = pictureBox1.Bottom + 40; } else { this.Height = pictureBox2.Bottom + 40; } } private void button1_Click(object sender, EventArgs e) { if (File.Exists(str[0]) && File.Exists(str[1])) { using (FileStream fs = new FileStream(str[0], FileMode.Open, FileAccess.ReadWrite)) //fs referenciája innentől kezdve ugyanaz. { byte[] bteredeti = new byte[fs.Length]; fs.Read(bteredeti, (int)0, (int)fs.Length); byte[] bt = File.ReadAllBytes(str[1]); pictureBox1.Image = Image.FromStream(fs); //picture1 forrása fs!!! fs.Seek(0, SeekOrigin.Begin); fs.SetLength(bt.Length); fs.Write(bt, 0, bt.Length); //fs bájtjai átírva, de a referencia ugyanaz!!! pictureBox2.Image = Image.FromStream(fs); //picture2 forrása is fs!!! //itt fs-ben csak az egyik kép van, de a 2 picturebox-ban mégis más kép van, tehát a image-ok eleve másolatok, nem azonos referencia!!! fs.Seek(0, SeekOrigin.Begin); fs.SetLength(bteredeti.Length); fs.Write(bteredeti, 0, bteredeti.Length); //fs-ben az eredeti tartalom fs.Close(); } pictureBox1.Width = pictureBox1.Image.Width; pictureBox2.Width = pictureBox2.Image.Width; pictureBox1.Height = pictureBox1.Image.Height; pictureBox2.Height = pictureBox2.Image.Height; pictureBox2.Left = pictureBox1.Right; //fájlnevek cseréje string temp = str[0]; str[0] = str[1]; str[1] = temp; } } private void button2_Click(object sender, EventArgs e) { if (File.Exists(str[0]) && File.Exists(str[1])) { //gond nélkül törölhető mind a kettő!!! File.Delete(str[0]); File.Delete(str[1]); } } } }

    Egy lényeg van: a filestreamet törlés előtt fel kell szabadítani.
    Mutasd a teljes hozzászólást!
  • Köszi, örülök, ha valakinek hasznos, mert néha nagyon frusztráló, hogy megoldom valakinek a problémáját, az illető meg oda sem bagózik - meglepően gyakori eset.

    Ugyanakkor némelyik probléma segít elmélyedni a részletekben, mint a mostani is.
    Mutasd a teljes hozzászólást!
  • Igen, igazad van, látszik, hogy az Image.FromStream() metódus új Image példányt készít, így ez az elmélet megdőlt.

    Amikor megvizsgáltam a problémát én az alábbi kóddal próbálkoztam:

    PictureBox1.Image = Image.FromFile(FotoName);

    és meglepve láttam, hogy tényleg fogja a file-t a process (más program nálam nem futott). Én nem ezt vártam, innen jutottam arra a következtetésre, hogy talán a referenciára mutat, de ez látszik, hogy nem így van.

    Most még egyszer megnéztem az eredeti kódot, és valóban, az úgy jól működik. Neked jár a pont.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd