将超时附加到WinRT中的异步请求

时间:2013-03-04 09:21:05

标签: c# exception-handling windows-runtime async-await dotnet-httpclient

我正在使用这段代码将TimeOut附加到我正在进行的请求调用中,以确保我们不会遇到缓慢的互联网连接 - 并且处理得当。 当我满足超时条件时,我收到一条错误消息,我无法在扩展功能中修复。

如何一般地完成这项任务?

代码:

public static class SOExtensions
{
    public static Task<T> WithTimeout<T>(this Task<T> task, TimeSpan duration)
    {
        return Task.Factory.StartNew(() =>
        {
            bool b = task.Wait(duration);
            if (b) return task.Result;
            return default(T);
        });
    }
}

用法:

var response = await HttpWebRequest
                     .Create(request)
                     .GetResponseAsync()
                     .WithTimeout(TimeSpan.FromSeconds(1));

我使用此处理AggregateException(并通过WebException),但在超时失败时仍会生成AggregateException

1 个答案:

答案 0 :(得分:2)

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

但如果你想要一个&#34;外部&#34;超时,更自然的方法是:

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;
}

这可以防止异常被包装到AggregateException中。但它不如CancellationToken方法有效,它看起来像这样:

var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(1));
var response = await new HttpClient().GetAsync(uri, timeout.Token);

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