0

我正在使用这段代码将 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这个(并通过 a WebException),但它仍然AggregateException在超时失败时生成。

4

1 回答 1

2

我建议使用CancellationTokenfor timeouts ( new CancellationTokenSource(myTimeSpan).Token),然后您可以您的async方法中使用它(例如, for 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;
}

这将防止异常被包装到一个AggregateException. 但是,它的效率不如这种CancellationToken方法,它看起来像这样:

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

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

于 2013-03-04T13:10:28.393 回答