Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel a RestSharp synchronous execute() call?

I have this line, which does a blocking (synchronous) web service call, and works fine:

var response = client.Execute<DataRequestResponse>(request);

(The var represents IRestResponse<DataRequestResponse>)

But, now I want to be able to cancel it (from another thread). (I found this similar question, but my code must stay sync - the code changes have to stay localized in this function.)

I found CancellationTokenSource, and an ExecuteTaskAsync() which takes a CancellationToken. (See https://stackoverflow.com/a/21779724/841830) That sounds like it could do the job. I got as far as this code:

var cancellationTokenSource = new CancellationTokenSource();
var task = client.ExecuteTaskAsync(request, cancellationTokenSource.Token);
task.Wait();
var response = task.Result;

The last line refuses to compile, telling me it cannot do an implicit cast. So I tried an explicit cast:

IRestResponse<DataRequestResponse> response = task.Result as IRestResponse<DataRequestResponse>;

That compiles, runs, but then crashes (throws a NullReferenceException, saying "Object reference not set to an instance of an object").

(By the way, once I have this working, then the cancellationTokenSource.Token will of course be passed in from the master thread, and I will also be adding some code to detect when an abort happened: I will throw an exception.)

My back-up plan is just to abort the whole thread this is running in. Crude, but that is actually good enough at the moment. But I'd rather be doing it "properly" if I can.

MORE INFORMATION:

The sync Execute call is here: https://github.com/restsharp/RestSharp/blob/master/RestSharp/RestClient.Sync.cs#L55 where it ends up calling Http.AsGet() or Http.AsPost(), which then ends up here: https://github.com/restsharp/RestSharp/blob/master/RestSharp/Http.Sync.cs#L194

In other words, under the covers RestSharp is using HttpWebRequest.GetResponse. That has an Abort function, but being a sync function (i.e. which does not return until the request is done) that is not much use to me!

like image 322
Darren Cook Avatar asked May 26 '15 09:05

Darren Cook


1 Answers

The async counterpart of your call

var response = client.Execute<DataRequestResponse>(request);

is the public virtual Task<IRestResponse<T>> ExecuteTaskAsync<T>(IRestRequest request, CancellationToken token) RestSharp async method.

It takes a cancellation token, and returns a task with the correct return type signature. To use it and wait for its (cancellable) completion, you could change your sample code to:

var cancellationTokenSource = new CancellationTokenSource();

// ...

var task = client.ExecuteTaskAsync<DataRequestResponse>(
    request,    
    cancellationTokenSource.Token);

// this will wait for completion and throw on cancellation.
var response = task.Result; 
like image 105
Alex Avatar answered Oct 02 '22 10:10

Alex