如何取消RestSharp同步execute()调用?

Dar*_*ook 5 c# mono multithreading restsharp

我有这一行,它执行阻塞(同步)Web服务调用,并且工作正常:

var response = client.Execute<DataRequestResponse>(request);
Run Code Online (Sandbox Code Playgroud)

(var代表IRestResponse<DataRequestResponse>)

但是,现在我希望能够取消它(来自另一个线程).(我发现了类似的问题,但我的代码必须保持同步 - 代码更改必须在此函数中保持本地化.)

我找到了CancellationTokenSource,而且ExecuteTaskAsync()需要一个CancellationToken.(见/sf/answers/1524580711/)听起来它可以完成这项工作.我得到了这段代码:

var cancellationTokenSource = new CancellationTokenSource();
var task = client.ExecuteTaskAsync(request, cancellationTokenSource.Token);
task.Wait();
var response = task.Result;
Run Code Online (Sandbox Code Playgroud)

最后一行拒绝编译,告诉我它不能进行隐式转换.所以我尝试了一个明确的演员:

IRestResponse<DataRequestResponse> response = task.Result as IRestResponse<DataRequestResponse>;
Run Code Online (Sandbox Code Playgroud)

编译,运行,然后崩溃(抛出NullReferenceException,说"对象引用未设置为对象的实例").

(顺便说一下,一旦我有了这个工作,那么cancellationTokenSource.Token当然会从主线程中传入,我也会添加一些代码来检测中止发生的时间:我将抛出异常.)

我的备份计划只是为了中止正在运行的整个线程.原油,但这实际上已经足够好了.但如果可以的话,我宁愿"正确地"做到这一点.

更多信息:

同步Execute调用在这里:https://github.com/restsharp/RestSharp/blob/master/RestSharp/RestClient.Sync.cs#L55 ,它最终调用Http.AsGet()Http.AsPost(),然后在此结束:https:// github. COM/restsharp/RestSharp/BLOB /主/ RestSharp/Http.Sync.cs#L194

换句话说,RestSharp正在使用HttpWebRequest.GetResponse.这有一个Abort功能,但是作为一个同步功能(即在请求完成之前不会返回)对我来说没什么用处!

Ale*_*lex 5

您呼叫的异步对应方

var response = client.Execute<DataRequestResponse>(request);
Run Code Online (Sandbox Code Playgroud)

public virtual Task<IRestResponse<T>> ExecuteTaskAsync<T>(IRestRequest request, CancellationToken token)RestSharp异步方法.

它需要一个取消令牌,并返回一个具有正确返回类型签名的任务.要使用它并等待其(可取消)完成,您可以将示例代码更改为:

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; 
Run Code Online (Sandbox Code Playgroud)


Dar*_*ook 0

鉴于此同步调用:

var response = client.Execute<MyData>(request);
process(response);
Run Code Online (Sandbox Code Playgroud)

将其更改为:

var response = null;
EventWaitHandle handle = new AutoResetEvent (false);
client.ExecuteAsync<MyData>(request, r => {
    response = r;
    handle.Set();
    });
handle.WaitOne();
process(response);
Run Code Online (Sandbox Code Playgroud)

这相当于同步版本,没有任何好处。这是添加中止功能的一种方法:

bool volatile cancelAllRequests = false;
...
var response = null;
EventWaitHandle handle = new AutoResetEvent (false);
RestRequestAsyncHandle asyncRequest = client.ExecuteAsync<MyData>(request, r => {
     response = r;
     handle.Set();
     });
 while(true){            
     if(handle.WaitOne(250))break;   //Returns true if async operation finished
     if(cancelAllRequests){
         asyncRequest.WebRequest.Abort();
         return;
         }
     }
process(response);
Run Code Online (Sandbox Code Playgroud)

(抱歉,等不及赏金结出果实,所以今天下午必须通过反复试验自己解决这个问题......)