Detección de la muerte del cliente en los contratos dúplex WCF

Estoy tratando de construir una SOA donde los clientes pueden realizar consultas de larga ejecución en el servidor y el servidor responde mediante una devolución de llamada.

Me gustaría poder detectar si el cliente se desconecta (a través del apagado iniciado por el usuario, la excepción no controlada o la pérdida de conectividad de la red) para que el servidor pueda elegir cancelar la solicitud costosa.

Estoy probando una variedad de casos de fallas pero parece que no puedo hacer que ciertos manejadores de eventos se activen.

Casos de falla probados: Matar el proceso del cliente después de la solicitud. Usando un programa como CurrPorts para cerrar la conexión TCP.

Código de prueba:

using System;
using System.ServiceModel;
using System.Threading;

namespace WCFICommunicationObjectExperiments
{
    class Program
    {
        static void Main(string[] args)
        {
            var binding = new NetTcpBinding(SecurityMode.None);

            var serviceHost = new ServiceHost(typeof (Server));
            serviceHost.AddServiceEndpoint(typeof (IServer), binding, "net.tcp://localhost:5000/Server");
            serviceHost.Open();
            Console.WriteLine("Host is running, press <ENTER> to exit.");
            Console.ReadLine();
        }

    }

    [ServiceContract(CallbackContract = typeof(IClient))]
    public interface IServer
    {
        [OperationContract]
        void StartProcessing(string Query);
    }

    public interface IClient
    {
        [OperationContract]
        void RecieveResults(string Results);
    }

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Server : IServer
    {

        public void StartProcessing(string Query)
        {
            Thread.Sleep(5000);

            //Callback Channel
            var clientCallback = OperationContext.Current.GetCallbackChannel<IClient>();
            var clientCallbackCommunicationObject = ((ICommunicationObject) clientCallback);
            EventHandler faultedHandlerCallback = (o, s) => Console.WriteLine("Client Channel Faulted.");
            EventHandler closedHandlerCallback = (o, s) => Console.WriteLine("Client Channel Closed.");
            clientCallbackCommunicationObject.Faulted += faultedHandlerCallback;
            clientCallbackCommunicationObject.Closed += closedHandlerCallback;

            //Request Channel
            var requestChannel = OperationContext.Current.Channel;
            EventHandler faultedHandlerRequest = (o, s) => Console.WriteLine("Request Channel Faulted.");
            EventHandler closedHandlerRequest = (o, s) => Console.WriteLine("Request Channel Closed.");
            requestChannel.Faulted += faultedHandlerRequest;
            requestChannel.Closed += closedHandlerRequest;

            try
            {
                clientCallback.RecieveResults("42.");
            }
            catch (CommunicationObjectAbortedException ex)
            {
                Console.WriteLine("Client Aborted the connection");
            }
            catch (CommunicationObjectFaultedException ex)
            {
                Console.WriteLine("Client Died.");
            }
            clientCallbackCommunicationObject.Faulted -= faultedHandlerCallback;
            clientCallbackCommunicationObject.Faulted -= closedHandlerCallback;
            requestChannel.Faulted -= faultedHandlerRequest;
            requestChannel.Closed -= closedHandlerRequest;
        }
    }

    public class ClientToTestStates : IClient
    {
        private IServer m_Server;

        private readonly ManualResetEvent m_ReceivedEvent = new ManualResetEvent(false);
        private readonly ManualResetEvent m_ChannelFaulted = new ManualResetEvent(false);
        private readonly ManualResetEvent m_ChannelClosed = new ManualResetEvent(false);

        public ClientToTestStates()
        {
            var binding = new NetTcpBinding(SecurityMode.None);
            var channelFactory = new DuplexChannelFactory<IServer>(this, binding, new EndpointAddress("net.tcp://localhost:5000/Server"));
            m_Server = channelFactory.CreateChannel();
            ((ICommunicationObject)m_Server).Open();
            ((ICommunicationObject)m_Server).Faulted += ChannelFaulted;
            ((ICommunicationObject)m_Server).Closed += ChannelClosed;

            m_Server.StartProcessing("What is the answer?");

            WaitHandle.WaitAny(new WaitHandle[] {m_ReceivedEvent, m_ChannelFaulted, m_ChannelClosed});
        }

        void ChannelFaulted(object sender, EventArgs e)
        {
            m_ChannelFaulted.Set();
            Console.WriteLine("Channel Faulted.");
        }

        void ChannelClosed(object sender, EventArgs e)
        {
            m_ChannelClosed.Set();
            Console.WriteLine("Channel Closed.");
        }


        public void RecieveResults(string results)
        {
            m_ReceivedEvent.Set();
            Console.WriteLine("Recieved Results {0}", results);
        }
    }
}

¿Cuál es la mejor práctica para manejar este tipo de casos de fallas? Me gustaría poder usar la conexión TCP subyacente para detectar algunas de estas cosas.