Search code examples
wcfiisbasichttpbindingcancellationlong-running-processes

Method of "cooperatively" terminating a WCF service (basic HTTP, non-duplex)


I have a WCF service that takes a long time to run. (For the sake of this question I am not interested in breaking up the service call.)

However, when a client disconnects forcibly the WCF service will continue to run to completion - even if the client will never receive the response.

I've found information about reliable messaging (which does not seem to apply here), duplex channels/behaviors (which I don't want to implement or require), and understand how it's possible to "break up" the service requests.

However, I was wondering if there might not be a "simple" method like the CancellationPending property of a background worker, the service would then look something like so:

while (!WCFRequest.CancellationPending && !FinishedWithLongOperation) {
   DoOnePartOfTheLongOperation();
}

If not, is there any way to add such? Or even kick the WCF thread with a harsh exception (ie. TheadInterruptedException)?

The service itself is designed to be fully idempotent wrt the completed work and reporting of such.


The WCF service is hosted in IIS 7, which I suspect may be relevant.


Solution

  • For a WCF Service that is hosted in IIS as an HTTP/HTTPS end-point I am using HttpResponse.IsClientConnected which Works Here (TM).

    Note: This depends on the ability of the hosting server (eg. IIS) to correctly detect a disconnect. In general these must be orderly disconnects. YMMV.

    The code is then functionally equivalent to:

    while (!FinishedWithLongOperation) {
        if (Connection.ClientConnectedStatus == ClientStatus.Disconnected) {
           throw new Exception("Client definitely disconnected!");
        }
        DoOnePartOfTheLongOperation();
    }
    

    Notes:

    • "Connection" is injected via Dependency Injection (so it could theoretically be altered to other stacks) and ..
    • .. ClientConnectedStatus returns one of {Connected, Disconnected, Unknown}; aborting only occurs when the client is "definitely disconnected" so that ..
    • .. if there is no IIS / HTTPContext then ClientConnectedStatus will always return Unknown and prevent potential false not-Connected situations (eg. if hosted otherwise).