Wątki i praca na jednym obiekcie-obrazie

0

Witam, mam następujący problem:
wczytuję obraz z dysku, a następnie muszę stworzyć kilka jego wersji różniących się rozmiarem i każdy taki obraz pociąć i zapisać na dysku. Ponieważ obrazy mogą być baaardzo duże to trochę trwa, więc chcę każde (resize, cięcie i zapis na dysk) zrobić osobno dla każdej wersji rozmiarowej.
Jednak tutaj pojawia się problem, bo gdy uruchamiam kilka wątków i każdemu przekazuję ten sam, oryginalny obraz na wejściu procedury, to wywala błąd że obiekt (obraz) jest już obecnie używany.
Czy mógłby ktoś mi pomóc jak to można rozwiązać?

Zaznaczam tylko że procedura zmieniająca rozmiar nie modyfikuje oryginalnego a tylko tworzy nowy na jego podstawie, oto ta procedura:

        public static Bitmap ResizeImage(Image img, double percent)
        {
            if (img == null)
                return null;
            if (percent <= 0)
                return null;

            percent = percent / 100.0;

            Bitmap bmp = new Bitmap(img);
            int srcWidth = bmp.Width;
            int srcHeight = bmp.Height;

            int destWidth = (int)(srcWidth * percent);
            int destHeight = (int)(srcHeight * percent);
            if (destWidth <= 0 || destHeight <= 0)
                return null;

            Bitmap b = new Bitmap(destWidth, destHeight);
            Graphics g = Graphics.FromImage(b);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(bmp, 0, 0, destWidth, destHeight);
            g.Dispose();

            return b;
        }//ResizeImage()

Dodam jeszcze że obrazy mogą być naprawdę duże, np. 5000x4000px

0

Jednak tutaj pojawia się problem, bo gdy uruchamiam kilka wątków i każdemu przekazuję ten sam, oryginalny obraz na wejściu procedury, to wywala błąd że obiekt (obraz) jest już obecnie używany.

Image jest typem referencyjnym, wiec do funkcji przekazujesz w praktyce 'wskazniki' do tego samego obiektu. A jeśli kilka wątków ma pracować na jedym, w tym przypadku, obrazku to może spróbuj do fukncji przekazać kopie (image.Clone() bodajże). Albo pokombinować z lock-iem?

0

Tak, wiem, że to typ referencyjny, tylko że ja tego obrazu nie zmieniam, co najwyżej jedynie czytam i na jego podstawie tworze inny, mniejszy. Ponieważ te obrazy są duże, dlatego nie chciałbym stosować kopii. Niestety nie wiem jak się posługiwać lock'iem i jak go w tym przypadku zastosować.

1

Nie testowałem, ale wydaje mi się że 1000x wydajniej będzie jednak copy... Bo lock ogranicza dostęp do obrazu tylko jednemu wątkowi, nawet do read. Zamiast szukać na zawnątrz na jakiejś lukaszowa ;), popatrz tutaj:
Bezpieczny dostęp do danych
(EDIT: jako że nie wszyscy będą na tyle przenikliwi żeby przeczytać cały artykuł, dodam że chodzi mi o ostatni akapit)
Da ci to coś?

Aha, ale po co ci kilka wątków 0_o??? Tworząc wiele wątków nie osiągasz zysku prędkości, iteracyjnie jest zawsze najszybciej... No chyba że masz 2rdzeniowy procesor, ale i wtedy 2 wystarczą...

0

jeszcze o tym 'lock' poczytam, ale wydaje mi się że to jednak nie będzie najlepsze, chociaż myślałem że między kolejnymi zapisami elementu na dysku (co jednak trwa), inne wątki mogłyby w tym czasie korzystać ze wspólnego obiektu. Ale rozwiąże to inaczej, podobnie jak copy, tylko że najpierw utworze zresizowane obrazy, zamiast całych dużych.
Jednak co do wątków, to zrobię to z ich pomocą niż iteracyjnie.

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