我的网络请求由此代码处理;
Response = await Client.SendAsync(Message, HttpCompletionOption.ResponseHeadersRead, CToken);
在读取响应标头之后和内容完成读取之前返回。当我打电话给这一行来获取内容时......
return await Response.Content.ReadAsStringAsync();
我希望能在X秒后停止它。但它不接受取消令牌。
答案 0 :(得分:10)
虽然可以依赖WithCancellation
进行重用,但是一个更简单的超时解决方案(不会抛出OperationCanceledException
)将创建一个超时任务Task.Delay
并等待使用Task.WhenAny
完成第一项任务:
public static Task<TResult> WithTimeout<TResult>(this Task<TResult> task, TimeSpan timeout)
{
var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult), TaskContinuationOptions.ExecuteSynchronously);
return Task.WhenAny(task, timeoutTask).Unwrap();
}
或者,如果你想在超时而不是仅返回默认值(即null
)时抛出异常:
public static async Task<TResult> WithTimeout<TResult>(this Task<TResult> task, TimeSpan timeout)
{
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
{
return await task;
}
throw new TimeoutException();
}
用法是:
var content = await Response.Content.ReadAsStringAsync().WithTimeout(TimeSpan.FromSeconds(1));
答案 1 :(得分:2)
看看How do I cancel non-cancelable async operations?。如果您只想在后台继续请求时完成await
,则可以使用作者的WithCancellation
扩展方法。这是从文章中复制的:
public static async Task<T> WithCancellation<T>(
this Task<T> task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using(cancellationToken.Register(
s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
if (task != await Task.WhenAny(task, tcs.Task))
throw new OperationCanceledException(cancellationToken);
return await task;
}
它基本上将原始任务与接受取消令牌的任务相结合,然后使用Task.WhenAny
等待这两项任务。因此,当您取消CancellationToken
时,secodn任务会被取消但原始任务会继续。只要你不关心它,你就可以使用这种方法。
你可以像这样使用它:
return await Response.Content.ReadAsStringAsync().WithCancellation(token);
<强>更新强>
您还可以尝试在取消时处理响应。
token.Register(Reponse.Content.Dispose);
return await Response.Content.ReadAsStringAsync().WithCancellation(token);
现在取消令牌时,Content
对象将被处理掉。
答案 2 :(得分:-3)
由于返回任务,您可以Wait
执行任务,这基本上等同于指定超时:
// grab the task object
var reader = response.Content.ReadAsStringAsync();
// so you're telling the reader to finish in X milliseconds
var timedOut = reader.Wait(X);
if (timedOut)
{
// handle timeouts
}
else
{
return reader.Result;
}