¿Por qué la tarea LongRunning (TPL) con JpegBitmapDecoder se queda sin recursos?

Tenemos una aplicación administrada .Net / C # que crea tareas TPL para realizar la codificación de metadatos JPEG en imágenes JPEG. Cada tarea se construye con la opción TaskCreationOptions.LongRunning, por ejemplo,

Task task = new Task( () => TaskProc(), cancelToken, TaskCreationOptions.LongRunning );

TaskProc () utiliza las clases JpegBitmapDecoder y JpegBitmapEncoder para agregar metadatos JPEG y guardar nuevas imágenes en el disco. Permitimos que hasta 2 de estas tareas estén activas al mismo tiempo, y este proceso debe continuar indefinidamente.

Después de algún tiempo de realizar lo anterior obtenemosNo hay suficiente espacio disponible para procesar este comando excepción al intentar crear una instancia de la clase JpegBitmapDecoder:

System.ComponentModel.Win32Exception (0x80004005): No hay suficiente almacenamiento disponible para procesar este comando en MS.Win32.UnsafeNativeMethods.RegisterClassEx (WNDCLASSEX_D wc_d)
en MS.Win32.HwndWrapper..ctor (Int32 classStyle, Int32 style, Int32 exStyle, Int3 2 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHoo k [] hooks) en System.Windows.Threading .Dispatcher..ctor () en System.Windows.Threading.Dispatcher.get_CurrentDispatcher () en System.Windows.Media.Imaging.BitmapDecoder..ctor (Stream bitmapStream, BitmapC reateOptions createOptions, BitmapCacheOption cacheOption) .Media.Imaging.JpegBitmapDecoder..ctor (Stream bitmapStream, Bit mapCreateOptions createOptions, BitmapCacheOption cacheOption)

El error ocurriósolamente cuando utilizamos JpegBitmapDecoder para agregar metadatos. En otras palabras, si la tarea solo codificaría y guardaría una imagen de mapa de bits en un archivo, no surgirían problemas. No se reveló nada obvio al usar Process Explorer, Process Monitor u otras herramientas de diagnóstico. No se observaron filtraciones de hilo, memoria o manija en absoluto. Cuando se produce tal error, no se pueden iniciar nuevas aplicaciones, por ejemplo, bloc de notas, word, etc. Una vez que se termina nuestra aplicación, todo vuelve a la normalidad.

La opción de creación de tareas de LongRunning se define en MSDN comoEspecifica que una tarea será una operación de larga duración y de grano grueso. Proporciona una sugerencia al TaskScheduler de que la suscripción excesiva puede estar justificada. Esto implica que el subproceso elegido para ejecutar la tarea puede no ser del ThreadPool, es decir, se creará para el propósito de la tarea. Las otras opciones de creación de tareas darán como resultado que se seleccione un subproceso ThreadPool para la tarea.

Después de un tiempo de análisis y prueba, cambiamos la opción de creación de tareas a algo que no seaLarga corrida, p.ej.,Preferir la equidad. No se hicieron otros cambios en el código en absoluto. Esto "resolvió" el problema, es decir, no más errores de almacenamiento.

Estamos desconcertados en cuanto a la razón real de que los hilos LongRunning sean los culpables. Aquí están algunas de nuestras preguntas sobre esto:

¿Por qué el hecho de que los hilos elegidos para ejecutar la tarea provengan de ThreadPool o no? Si el subproceso termina, GC no debería recuperar sus recursos a lo largo del tiempo y devolverlos al sistema operativo, independientemente de su origen.

¿Qué tiene de especial la combinación de una tarea LongRunning y la funcionalidad JpegBitmapDecoder que causa el error?

Respuestas a la pregunta(2)

Su respuesta a la pregunta