2010-11-24 13 views
12

He implementado un servicio WCF como tal:Servicio WCF e IDisposable, ¿limpio los objetos gestionados?

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext=false)] 
public sealed class SynchronizationService : ISynchronizationService, IDisposable 
{ 
    private MemoryStream objectStream; 

    ... 
} 

ISyncrhonizationService tiene [ServiceContract (SessionMode = SessionMode.Required)].

Si un cliente se comunica correctamente y finalmente llama a un método con [IsTerminating = true], entonces puedo deshacerme de la variable objectStream muy bien. Si por alguna razón la comunicación entre el servicio y el cliente se interrumpe, me gustaría limpiar la variable objectStream desde el lado del servicio, por lo que deseo implementar la interfaz IDisposable. Pero al mirar a la documentación de MSDN (http://msdn.microsoft.com/en-us/library/system.idisposable.aspx) Soy un poco escéptico acerca de esto, porque según la documentación:

// Dispose(bool disposing) executes in two distinct scenarios. 
    // If disposing equals true, the method has been called directly 
    // or indirectly by a user's code. Managed and unmanaged resources 
    // can be disposed. 
    // If disposing equals false, the method has been called by the 
    // runtime from inside the finalizer and you should not reference 
    // other objects. Only unmanaged resources can be disposed. 

Debido a que es el tiempo de ejecución que llamará al método Dispose luego desechar = false. Por lo tanto, no debería acceder a objectStream, porque es un objeto administrado. En este caso, el finalizador SyncrhonizationService proporcionado por el tiempo de ejecución debe limpiarse de objectStream y no es necesario implementar IDisposable en absoluto. Sin embargo, algunas publicaciones en el foro sugieren que la instancia de SyncrhonizationService se reutilizará y no se descartará/finalizará.

Así que mis preguntas son:

1) ¿Qué ocurre en realidad a la instancia durante SyncrhonizationService excepciones/Fallos/tiempos de espera/etc? ¿Se eliminará o simplemente se reutilizará más adelante?

2) ¿Debo implementar IDisposable y deshacerme de los objetos gestionados dentro del método Dispose()?

3) ¿Existe quizás una mejor alternativa a IDisposable, por ejemplo algo así como un evento channel_Faulted? Si elimino mis objetos gestionados en tal caso, ¿cómo y dónde eliminaré el controlador de eventos (podría hacerlo en el controlador de eventos, pero qué pasa si ocurre otro tipo de excepción/falla)?

+4

Tenga en cuenta que IDisposable no tiene una sobrecarga Dispose (bool). Los comentarios entrecomillados de MSDN están documentando el ejemplo de código proporcionado, sin especificar el comportamiento IDisposable. El finalizador no llamará automáticamente a Dispose: debe codificarlo explícitamente para hacerlo como se muestra en el ejemplo del código. Agregar una anulación de Dispose (bool) como se muestra en el ejemplo de código es el patrón estándar para hacer esto. En el caso de su servicio, puede estar seguro de que WCF llamará a su método Dispose() cuando finalice la sesión, por lo que no necesita (y no debería tener) un finalizador. –

+0

Gracias por aclarar eso, ahora todo tiene sentido :) – Marko

Respuesta

18

Si implementa IDisposable, puede limpiar los objetos gestionados dentro de su implementación del método Dispose().

Con PerSession InstanceContextMode, el tiempo de ejecución de WCF llamará a Dispose en su objeto SynchronisationService cuando finalice la sesión, ya sea porque el cliente cerró su proxy; debido al tiempo de espera de la sesión por inactividad (en el cliente o servidor); o a través del canal fallando.

La instancia de servicio no se reutilizará: las sesiones nuevas obtendrán nuevas instancias de su SynchronisationService.

Cuestiones relacionadas