Cocowalla Cocowalla - 11 months ago 66
HTTP Question

How to cancel ServiceStack async request?

I'm using ServiceStack v4, and making an async request like:

var client = new JsonServiceClient(url);
Task reqTask = client.GetAsync(request);

I'll be making a lot of requests simultaneously to different servers, and need to support cancellation to immediately cancel all outstanding calls. The underlying
has a method
, but it doesn't seem to do anything.

How can I cancel the request such that it aborts the web request immediately?

Answer Source

Short version, it seems that CancelAsync does nothing indeed.

Looking at the code, it seems that ServiceStack uses the old way (v3) of asynchronously executing requests and notifying you with with callbacks, all built on top of WebRequest and the APM-style calls (BeginXXX,EndXXX). The GetAsync, SendAsync methods are actually wrappers that use a TaskCompletionSource to provide a Task based interface over the actual asynchronous operation.

CancelAsync actually calls a CancelAsyncFn delegate that isn't set by the classes in JsonServiceClient's hierarchy, so calling it actually does nothing. I suspect this is provided to create custom clients and actions.

In any case, cancelling an HTTP request isn't so easy as it sounds. You need to understand what it is that you are trying to cancel.

  1. You can't actually cancel the call to the server once it's left your application.
  2. You can't tell the server or the intervening devices to stop processing, as HTTP doesn't provide such a mechanism. The server has to provide such an API, which is actually a new HTTP call.
  3. You can't prevent the server from sending a response
  4. You can cancel sending the entire request to the server. This will only work for requests that take a detectable amount of time to serialize
  5. You can ignore the server's response and refuse to open a stream to read the body
  6. You can stop reading the response from the server
  7. You can simply ignore the results of the operation

Looking at the code, it seems that you can't do #4, #5 or #6, because AsyncServiceClient doesn't expose the IAsyncResult used internally. The only thing you can do is simply ignore the response and pay the price of deserialization. Note, the same applies if you use HttpClient's GetStringAsync methods instead of executing each individual step.

So, if cancel means abandoning the request, you can do this by simply ignoring the return value. If it means stop server processing, you can't.