2011-06-01 7 views
10

En lugar de realizar la limpieza en el mismo subproceso (o iniciar un subproceso y bloquear hasta que finalice) inicie la limpieza en un "fondo" (IsBackground = falso, para que no termine prematuramente) y vuelva inmediatamente.¿No es una buena idea escribir el método Dispose/Close para que sea asincrónico?

¿Cuándo es esta una mala idea y qué tan mala? ¿Alguna vez esta es una buena idea?

+2

¿Es esto un pensamiento abstracto o tienes un recurso real no administrado que está tomando mucho tiempo para derribar (si es así, qué es, estoy intrigado)? – Lazarus

+0

Más de un pensamiento abstracto. Estaba mirando algunos objetos IO identificables y pensé: "Deberías intentar hacer todo IO de forma asíncrona porque Dios sabe cuánto tardará. Espera, ¿esto también se aplica a los destructores? De ser así, ¿por qué no hacerlos asíncronos por defecto (al usar bloques)? –

+0

Estoy bastante seguro de que el GC se ejecuta en un subproceso dedicado por lo que es, en efecto, concurrente, es decir, el objeto está marcado para la recopilación y su aplicación continúa ejecutándose. Eso es cierto para el perfil del cliente al menos, creo que el perfil del servidor puede tener el bloqueo del GC. – Lazarus

Respuesta

4

Reemplazar el Dispose() del IDisposable con una limpieza asincrónica viola el Liskov Subsitution Principle como sería de esperar que los recursos estuvieran disponibles de nuevo inmediatamente después de la llamada.

Supongo que esto es una optimización necesaria debido a la frecuente asignación/desasignación, lo que significaría que al final puede cambiar el problema a una cantidad creciente de objetos pendientes para eliminarse en el hilo de fondo. Eso conducirá a una escasez de memoria durante un tiempo más prolongado y necesitará alguna sincronización para asegurarse de que la cantidad de estos objetos no crezca hasta el cielo.

Como dijo Lazarus, una solución más adecuada podría ser tener un pool of reusable objects.

+0

Solo por curiosidad, ¿podría ampliar cómo una implementación asincrónica en un método de eliminación viola el LSP? Soy bastante nuevo y siento que me falta algo aquí. – Lazarus

+0

LSP significa que cada objeto que implementa IDisposable debe tener la misma semántica fuerte.Si considera el ejemplo de un flujo en un archivo exclusivamente, si lo cierra, inmediatamente después del Dispose/Close puede abrir otro Stream al archivo. Ese no sería el caso si el Dispose fuera asíncrono, lo que llevaría a una violación LSP en mi opinión. – jdehaan

+0

En algunos casos, un Dispose asincrónico violaría el LSP. En otros casos, no sería así. Una eliminación asíncrona puede ser segura para recursos fungibles (por ejemplo, GdiHandles) donde a nadie le va a importar cuando se libera un identificador en particular, pero uno quiere evitar que las manijas abandonadas se acumulen; también puede ser útil en casos donde se puede diferir cualquier intento de usar un recurso cuya limpieza se ha aplazado hasta después de que se complete la limpieza. – supercat

1

Un lugar que no desearía hacer es si su objeto es mantener algunos recursos limitados que otros hilos podrían estar esperando usar.

Estoy muy interesado en ver otras respuestas, ya que creo que esta es una idea interesante, y podría ser una buena manera en algunos casos de devolver datos al usuario más rápido.

5

Creo que querría mirar con cuidado en el momento de deshacerse de su recurso no administrado en comparación con el de iniciar el hilo de fondo. Si se trata de un proceso muy utilizado, podría encontrarlo generando una sobrecarga significativa, en el mejor de los casos.

Si el recurso no administrado es muy costoso de crear y destruir, entonces quizás podría considerar mantener una instancia común o conjunto de instancias durante la vida de su aplicación.

0

Un método de eliminación no debería volver hasta que se hayan completado todos los efectos esperados en los que puede confiar el otro código. Es razonable que Dispose posponga las tareas de limpieza cuando hacerlo no romperá las expectativas de otros códigos. Por ejemplo, el método Dispose para una clase de agrupación de conexiones puede agregar inmediatamente conexiones Disposed a un grupo sin cerrarlas, y tener un hilo de fondo que cierra las conexiones que no se han utilizado durante un tiempo. Si hay un límite para la cantidad de conexiones diferentes que pueden estar abiertas y no se puede satisfacer una solicitud porque el grupo está lleno de conexiones en caché (pero actualmente no se usan) que no son adecuadas para la presente solicitud, el método "Abrir" debe ser capaz de acelerar la limpieza de la piscina.

Cuestiones relacionadas