Mam do czynienia z problemem, którego nie jestem w stanie rozwiązać ani znaleźć rozwiązania Google.Usługa Windows: użycie BitmapEncoder lub BitmapDecoder kończy się słowem «Operacja zakończona powodzeniem»
Mam uruchomioną usługę, która ładuje lub zapisuje obrazy i używa klas BitmapEncoder
lub BitmapDecoder
. Po pewnym czasie (w zależności od tego, jak często zapisuję/ładuję obrazy) serwis odmawia zapisania/załadowania zdjęć. Najpierw Patrz ostrzeżenie w dzienniku zdarzeń z
alokacji sterty udało
google co to znaczy i że ma do czynienia z ograniczoną liczbę obiektów GDI, że usługa Windows ma. Jest możliwa modyfikacja rejestru w celu zwiększenia liczby tych obiektów, ale wydaje mi się, że nie jest to bardzo dobre rozwiązanie, a także nie działa dla mnie.
Mój kod rzuca następujący wyjątek z ślad stosu podczas zapisywania
Error while storing image : System.ComponentModel.Win32Exception (0x80004005): The operation completed successfully
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.DispatcherObject..ctor()
at System.Windows.Media.Imaging.BitmapEncoder..ctor(Boolean isBuiltIn)
at Imaging.TiffReadWrite.Save(String filename, Image img)
i podczas ładowania
Error while loading image : System.ComponentModel.Win32Exception (0x80004005): The operation completed successfully
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.DispatcherObject..ctor()
at System.Windows.Media.Imaging.BitmapDecoder..ctor(Stream bitmapStream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, Guid expectedClsId)
at Imaging.TiffReadWrite.Load(String filename)
mojego kodu do zapisywania obrazów wygląda następująco:
public static void Save(string filename, BitmapSource img)
{
using (FileStream stream = new FileStream(filename, FileMode.Create))
{
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.None;
BitmapFrame frm = BitmapFrame.Create(img);
encoder.Frames.Add(frm);
encoder.Save(stream);
}
}
i do ładowania obrazów wygląda tak:
public static BitmapSource Load(string filename)
{
BitmapSource resultImage = null;
using (Stream imSource = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var decoder = new TiffBitmapDecoder(imSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
resultImage = decoder.Frames[0];
}
return resultImage;
}
Usługa odmawia zapisania/załadowania zdjęć. Mogę spróbować/wychwycić ten wyjątek, aby usługa mogła nadal działać, ale nie można zapisać ani załadować żadnych obrazów. Czasami po pierwszym wystąpieniu tego wyjątku można zapisać/załadować kilka obrazów i po pewnym czasie nie jest wykonywane zapisywanie/ładowanie.
Jedynym sposobem obejścia tego problemu nie jest uruchomienie tego kodu w usłudze, ale w aplikacji. Wtedy działa dobrze, ale to nie jest rozwiązanie, którego szukam. Jeśli ktoś ma jakąś lepszą sugestię, proszę dać mi znać.
Istnieje kilka podobnych postów (ślad stosu wyjątku jest mniej więcej taka sama), które w rzeczywistości nie jest rozwiązany:
Does that mean an object doesn't need to be cleared manually if it doesn't implement IDisposable?
Windows.Media.Imaging Thumbnail generation causing exceptions
Cóż, to całkiem bezużyteczny komunikat wyjątku. Usługi działają w sesji 0, ma celowo małą stertę pulpitu. To sprawia, że bardziej prawdopodobne jest, że CreateWindowEx() zawiedzie. Może to być inna usługa, która nieuczciwie się z nią dzieli. Lub twój, licznik "Obiekty użytkownika" w Menedżerze zadań jest twoim pierwszym diagnostycznym. Ryzykujesz również, że GC nie gromadzi się wystarczająco często, możesz potrzebować pomocy, wywołując GC.Collect() samodzielnie każdą bitmapę N. Fakt, że nie ma znaczącego kodu błędu, wskazuje jednak na problem środowiskowy. –
Dziękuję za odpowiedź. Wiem, że jest niejasna i dlatego nie jestem w stanie jej rozwiązać. Sprawdzam Menedżera zadań i użyłem dheapmon do śledzenia obiektu GDI, w którym dowiedziałem się, że WinLogon ma wysoki wskaźnik wykorzystania, ale to wszystko. Może to być inna usługa, ale zaobserwowano ją na różnych komputerach na różnych usługach korzystających z opublikowanego przeze mnie kodu. To mało prawdopodobne. Myślę, że mam już wystarczająco dużo połączeń GC.Collect(). Więc to też nie pomoże. –
@ TomKos, rozważ użycie wartości 'BitmapCacheOption.None' jako argumentu konstruktora klasy' TiffBitmapDecoder' oraz jako argumentu wywołania metody 'BitmapFrame.Create()'. –