Jak usunac plik ktory jest aktualnie uzywany przez program?

0

Witam mam maly problem i znow zbytnio nie wiem jak go rozwiazac...
Mam picturebox'y w ktorych wyswietlam zdjecie...nad kazdym z nim mam checkbox'a za pomoca ktorego moge zaznaczyc obrazy ktore maja zostac usuniete...
Problem polega na tym ze w momencie usuwania pliku te juz sa uzywane przez picturebox'y...wiec dostaje wyjatek System.IO.IOException...
Kod wyglada tak:

 
        private void usunZaznaczoneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            for(int i = 0; i < this.imagePathToDelete.Count; i++)
            {
                try
                {
                    try
                    {
                        try
                        {

                            System.IO.File.Delete(this.imagePathToDelete[i].ToString());
                            MessageBox.Show("Wybrane obrazy zostaly usuniete");
                        }

                        catch (System.IO.IOException handleInUse)
                        {
                            MessageBox.Show(handleInUse.Message);
                        }
                    }

                    catch (ArgumentNullException nullPath)
                    {
                       MessageBox.Show(nullPath.Message);
                    }
                }

                catch (UnauthorizedAccessException readOnlyOrOnlyDir)
                {
                    MessageBox.Show(readOnlyOrOnlyDir.Message);
                }
            }  
        }

Hmm jak moge ominac ten problem...?
Czy blok finally tak czy siak by usunol plik?
Jakies inne rady?
Sry ze tak truje dupe....xD

0

Yyy... Przede wszystkim - po jasny gwint te zagnieżdżone try...catch? Tak się nie robi, wystarczy jeden try i odpowiednia sekwencja catch.

Po drugie, przed usunięciem pliku musisz go zwolnić, nie ma innej rady.

0

Po drugie, przed usunięciem pliku musisz go zwolnić, nie ma innej rady.

Swieta prawda....ale pytam bo nie bardzo wiem jak zwolnic zasob...w tym przypadku plik...ogolnie do tego sluzy dispose() ale jak moge zwolnic uzywany obraz z picturebox'a?

A co do try-catch jak to moge zrobic za pomoca jednego bloku?

btw: chodzi o using?

0

Nie wiem jak wczytujesz plik, więc Ci nie poradzę. W każdym razie Twój proces uzyskuje w pewnym momencie dostęp do pliku, więc system operacyjny nie dopuszcza już innych procesów do niego (włącznie z Twoim). Tu nie chodzi o zwalnianie w sensie Dispose.

Co do wyjątków - serio, łatwiej by Ci było, gdybyś przeczytał jakiś tutorial o podstawach C#.
Mniej więcej tak:

 
try
{
    System.IO.File.Delete(this.imagePathToDelete[i].ToString());
    MessageBox.Show("Wybrane obrazy zostaly usuniete");
}
catch (System.IO.IOException handleInUse)
{
    MessageBox.Show(handleInUse.Message);
}
catch (ArgumentNullException nullPath)
{
    MessageBox.Show(nullPath.Message);
}
catch (UnauthorizedAccessException readOnlyOrOnlyDir)
{
    MessageBox.Show(readOnlyOrOnlyDir.Message);
}

Tylko ważna jest kolejność, najbardziej szczegółowe wyjątki łapie się najpierw.

0

Obraz w pewnym momencie laduje tak:

 
pictureBox.Image = new System.Drawing.Bitmap(Convert.ToString(path[i]));
//lub
pictureBox.Image = System.Drawing.Image.FromFile(Convert.ToString(path[i]));

Jak to pozniej zwolnic przed usunieciem?
Probowalem using/dispose()/gc.collect() i nic ;]

Co do tych wyjatkow....to ona w tabeli na msdn sa w kolejnosci od najwazniejszego czy jako?bo skad mam wiedziec ktory jest pierwszy?

1

Nie using, nie Dispose, a zwłaszcza nie GC.Collect(). TO NIE MA ZWIĄZKU Z PAMIĘCIĄ, BLOKUJESZ PLIK NA DYSKU! Widzisz różnicę między pamięcią RAM a dyskiem twardym?

Musiałbyś odpalić Dispose na swoim PictureBoxie, żeby zwolnił plik, który nim blokujesz.

Musisz:
a) odczytać plik (strumień) z dysku;
b) załadować go do PictureBoxa;
c) zamknąć plik (strumień).

Mniej więcej tak:

using(FileStream fs = new FileStream(@"D:\plik.jpg", FileMode.Open, FileAccess.Read))
{
    this.pictureBox1.Image = Image.FromStream(fs);
}
0

Wiem jaka jest roznica....nie kodze od 2 tygodni...

 
using (System.IO.FileStream fs = new System.IO.FileStream(path[i].ToString(), System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
    pictureBox.Image = System.Drawing.Image.FromStream(fs);
}

Ok to dziala...
Czyli jednak nasz GC z .net nie jest taki wspanialy....myslalem ze takie zasoby sam zwolni skoro nie ma metod do blokowania pliku jesli dwa "procesy' chca miec do niego dostep w tym samym momencie...
Po robieniu dispose() na picturebox'ie oczywiscie gdy ten juz zostal dodany na forme dostawalem jakis blad...
Zasadniczo using dziala podobnie jak try-finally...oprocz tego ze sprawdza czy dany obiekt istnieje i ogranicza jego zasieg...wiec czemu tylko za pomoca using dziala.... ;]...?
To jest pytanie bo dlaczego byl blad i jak go rozwiazac to wiedzialem...nie rozumiem tylko dlaczego tak sie dzieje...

Tak jeszcze jedno pytanie...po usunieciu pliku jak moge zrobic update formy?Zeby picturebox'y ktore zawieraja obraz ktory zostal usuniety zniknely?
Czy jest na to jakis prosty sposob?
nie chce rozwiazania tylko czego mam szukac....refresh/invalidate nic nie daja..

mysle ze musialbym usunac instancje picturebox'ow ktore nie sa juz potrzebne i na nowo je "wsadzic" na forme tylko nie wiem czy dobrze mysle...;p

1

Nasz GC jest wspaniały, tylko trzeba umieć go poprawnie używać...

@somekind - ściśle to jest możliwość usunięcia pliku zajętego przez inny program (Icewall kiedyś napisał na ten temat na swoim blogu) ale to zajęcie na pograniczu czarnej magii (i przydatne usprawiedliwione tylko przy tworzeniu albo walczeniu z wirusami) :P

0
marcio napisał(a)

Czyli jednak nasz GC z .net nie jest taki wspanialy....myslalem ze takie zasoby sam zwolni skoro nie ma metod do blokowania pliku jesli dwa "procesy' chca miec do niego dostep w tym samym momencie...

Otworzyłeś plik i go nie zwolniłeś. Czego zatem oczekujesz od GC? Co niby miałby zrobić z zasobem, którego UŻYWASZ?
Przecież GC czyści pamięć i zwalnia zasoby, których już się nie używa.

Po robieniu dispose() na picturebox'ie oczywiscie gdy ten juz zostal dodany na forme dostawalem jakis blad...

No to chyba oczywiste. Dispose() woła się na obiektach, których już nie używamy. :|

To jest pytanie bo dlaczego byl blad i jak go rozwiazac to wiedzialem...nie rozumiem tylko dlaczego tak sie dzieje...

Setny raz powtarzam - otwierasz plik i go nie zwalniasz.

Ty wczytujesz plik bezpośrednio do PictureBoxa, ten ciągle korzysta z tego pliku. Ja w swoim kodzie używam strumienia do odczytania z pliku, potem dane ze strumienia ładuję do PictureBoxa, a potem zamykam strumień i zwalniam plik. Rozumiesz różnicę?

0

Za pomoca strumieni ok...rozumiem...wiem o co kaman ;]

Chodzilo mi o to ze wczytujac obraz za pomoca:

pictureBox.Image = new System.Drawing.Bitmap(Convert.ToString(path[i]));
//lub
pictureBox.Image = System.Drawing.Image.FromFile(Convert.ToString(path[i]))
 

Czyli nie uzywajac strumieni...nie ma tam metod Close() ani nic podobnego zeby zwolnic wczytany obraz...i tego nie kumalem...i dalej moje pytanie brzmi wczytujac obraz metodami powyzej idzie w jakis sposob zwolnic "zasob" nie uzywajac strumieni?
Bo jesli nie to wczytywanie zdjec za pomoca Bitmap()/FromFile() mija sie z celem...

1

Wydaje mi się, że to Bitmap możesz wstawić w using zamiast FileStream i zachowa się tak samo. Natomiast nie znam sposobu zrobienia tego przy użyciu statycznej metody Image.FromFile.

0

Użyj metody GetThumbnailImage. Plik nie jest blokowany i można go usunąć.

 Image imgMain = null;
 using (Image imgLoad = System.Drawing.Image.FromFile("sciezka"))
                {
                        imgMain = imgLoad.GetThumbnailImage(imgLoad.Width, imgLoad.Height, null, new IntPtr());
                }

1 użytkowników online, w tym zalogowanych: 0, gości: 1