C# 向WinRT中的异步请求追加超时

C# 向WinRT中的异步请求追加超时,c#,exception-handling,windows-runtime,async-await,dotnet-httpclient,C#,Exception Handling,Windows Runtime,Async Await,Dotnet Httpclient,我使用这段代码在请求调用中附加一个超时,以确保我们不会遇到缓慢的internet连接,并确保其得到适当处理。 当我满足超时条件时,我会收到一条错误消息,我无法在扩展函数中修复该消息 一般来说,如何进行这项任务 代码: 我用它处理aggregateeexception(并通过WebException),但超时失败时,它仍会生成aggregateeexception 我建议对超时使用CancellationToken(new CancellationTokenSource(myTimeSpan).T

我使用这段代码在请求调用中附加一个超时,以确保我们不会遇到缓慢的internet连接,并确保其得到适当处理。
当我满足超时条件时,我会收到一条错误消息,我无法在扩展函数中修复该消息

一般来说,如何进行这项任务

代码:


我用它处理
aggregateeexception
(并通过
WebException
),但超时失败时,它仍会生成
aggregateeexception

我建议对超时使用
CancellationToken
new CancellationTokenSource(myTimeSpan).Token
),然后可以在
async
方法中使用(例如,对于
HttpClient
,将令牌传递给
GetAsync
方法)。这会占用更少的资源,因为HTTP请求本身已被取消

但如果您想要“外部”超时,更自然的方法是:

public static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan duration)
{
  var timeout = Task.Delay(duration);
  var completeTask = await Task.WhenAny(task, timeout);
  if (completeTask == timeout)
    return default(T);
  else
    return await task;
}

请注意,
CancellationToken
方法将抛出
OperationCanceledException
,而不是在超时时返回
default(T)

效果很好,谢谢。我将在下一个sprint中尝试CancellationToken位,并在这里报告。实际上对我不起作用。它不再超时,并声称我没有处理WebException,即使我已经处理了WebException。我们将尝试第二种方法,然后标记answerCancellationToken,这是一种方法,但遗憾的是,当你在线搜索时,它并不那么清晰。感谢Stephen。Stephen:只有当CancellationToken超时小于HttpClient.timeout时,才能使用CancellationToken进行HttpClient.GetAsync超时。这是一个有点烦人的设计决策,也是我所看到的混乱和相当多的bug的来源,但我怀疑这个bug不太可能改变。
var response = await HttpWebRequest
                     .Create(request)
                     .GetResponseAsync()
                     .WithTimeout(TimeSpan.FromSeconds(1));
public static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan duration)
{
  var timeout = Task.Delay(duration);
  var completeTask = await Task.WhenAny(task, timeout);
  if (completeTask == timeout)
    return default(T);
  else
    return await task;
}
var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var response = await new HttpClient().GetAsync(uri, timeout.Token);