在任务中中止GetResponseAsync()和异常

时间:2014-04-01 20:18:43

标签: c# async-await

我写了一个从eq获得ETag的方法。服务器上的XML文件。如果超时(GetResponseAsync()没有CancellationToken)并且我不知道如何做Exception,我是否正确写入中止任务。

以下是代码:

    public static async Task<string> GetETagAsync(Uri feedLink)
    {
        const int millisecondsTimeout = 2500;
        WebRequest webRequest = WebRequest.Create(feedLink);
        webRequest.Method = "HEAD";
        try
        {
            Task<WebResponse> webResponse = webRequest.GetResponseAsync();
            if (await Task.WhenAny(webResponse, Task.Delay(millisecondsTimeout)) == webResponse)
            {
                using (var result = webResponse.Result)
                {
                    return result.Headers["ETag"];
                }
            }
            else
            {
                webRequest.Abort();
                return null;
            }
        }
        catch (Exception)
        {
            return null;
        }
    }

修改

我做了一些改变。重写异常并使用此主题中的类:GetResponseAsync does not accept cancellationToken

代码:

    public static async Task<string> GetETagAsync(Uri feedLink)
    {
        const int millisecondsTimeout = 2500;
        var cancellationTokenSource = new CancellationTokenSource();
        WebRequest webRequest = WebRequest.Create(feedLink);
        webRequest.Method = "HEAD";

        try
        {
            Task<WebResponse> webResponse = WebRequestExtensions.GetResponseAsync(webRequest, cancellationTokenSource.Token);
            if (await Task.WhenAny(webResponse, Task.Delay(millisecondsTimeout)) == webResponse)
            {
                using (var result = webResponse.Result)
                {
                    return result.Headers["ETag"];
                }
            }
            else
            {
                cancellationTokenSource.Cancel();
                return null;
            }
        }
        catch (AggregateException ex)
        {
            if (ex.InnerException is WebException)
                return null;

            throw;
        }
    }

public static class WebRequestExtensions
{
    public static async Task<WebResponse> GetResponseAsync(this WebRequest request, CancellationToken cancellationToken)
    {
        using (cancellationToken.Register(() => request.Abort(), useSynchronizationContext: false))
        {
            try
            {
                var response = await request.GetResponseAsync();
                cancellationToken.ThrowIfCancellationRequested();
                return (WebResponse)response;
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.RequestCanceled)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    throw new TaskCanceledException(ex.Message, ex);
                }

                throw;
            }
        }
    }
}

现在是否正确?

2 个答案:

答案 0 :(得分:3)

您可以使用我在此处写的WebRequestExtensions类来解决此问题: https://github.com/openstacknetsdk/openstack.net/blob/master/src/corelib/Core/WebRequestExtensions.cs

此类完全支持CancellationTokenWebRequest.Timeout属性。

答案 1 :(得分:1)

由于该方法本身不支持任何停止任务的方法,因此无法停止。你无能为力,这将阻止它继续做任何计划。您可以做的是确保此异步方法的任务不等待它完成。虽然你可以像往常一样返回一个值,但这似乎代表了一个例外情况;你可能应该抛出一个异常来表示操作超时。