我有这一行,它执行阻塞(同步)Web服务调用,并且工作正常:
var response = client.Execute<DataRequestResponse>(request);
(var
代表IRestResponse<DataRequestResponse>
)
但是,现在我希望能够取消它(来自另一个线程)。 (我发现了这个similar question,但我的代码必须保持同步 - 代码更改必须在此函数中保持本地化。)
我找到了CancellationTokenSource
,ExecuteTaskAsync()
找到了CancellationToken
。 (见https://stackoverflow.com/a/21779724/841830)听起来它可以完成这项工作。我得到了这段代码:
var cancellationTokenSource = new CancellationTokenSource();
var task = client.ExecuteTaskAsync(request, cancellationTokenSource.Token);
task.Wait();
var response = task.Result;
最后一行拒绝编译,告诉我它不能进行隐式转换。所以我尝试了一个明确的演员:
IRestResponse<DataRequestResponse> response = task.Result as IRestResponse<DataRequestResponse>;
编译,运行,但随后崩溃(抛出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/master/RestSharp/Http.Sync.cs#L194
换句话说,RestSharp正在使用HttpWebRequest.GetResponse。它有一个Abort
函数,但它是一个同步函数(即在请求完成之前不会返回)对我来说没什么用处!
答案 0 :(得分:5)
通话的异步对应
var response = client.Execute<DataRequestResponse>(request);
是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;
答案 1 :(得分:0)
鉴于此同步通话:
var response = client.Execute<MyData>(request);
process(response);
将其更改为:
var response = null;
EventWaitHandle handle = new AutoResetEvent (false);
client.ExecuteAsync<MyData>(request, r => {
response = r;
handle.Set();
});
handle.WaitOne();
process(response);
这相当于同步版本,没有获得任何好处。这是添加中止功能的一种方法:
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);
(对不起,等不及赏金结果,所以不得不为我自己做这件事,今天下午通过反复试验......)