【问题标题】:Task fromAsync timeout来自异步超时的任务
【发布时间】:2011-09-10 00:17:38
【问题描述】:

我有这段代码可以发出异步 HTTP 请求:

    public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
    {
        WebRequest request = WebRequest.Create(uri);
        request.Proxy = null;

        Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task =>
            {
                WebResponse response = task.Result;
                Stream responseStream = response.GetResponseStream();
                responseCallback(new RequestCallbackState(response.GetResponseStream()));
                responseStream.Close();
                response.Close();
            });
    }

它有效,但我需要设置请求超时。我尝试使用 request.Timeout 但似乎什么也没做。有没有办法在这段代码中设置任务超时?

已编辑以添加新的超时回调。 新代码:

    public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
    {
        WebRequest request = WebRequest.Create(uri);
        request.Proxy = null;

        IAsyncResult t = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task =>
            {
                WebResponse response = task.Result;
                Stream responseStream = response.GetResponseStream();
                responseCallback(new RequestCallbackState(response.GetResponseStream()));
                responseStream.Close();
                response.Close();
            });
        ThreadPool.RegisterWaitForSingleObject(t.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, 1000, true);
    }

    private static void TimeoutCallback(object state, bool timedOut)
    {
        if (timedOut)
        {
            Console.WriteLine("Timeout");
            WebRequest request = (WebRequest)state;
            if (state != null)
            {
                request.Abort();
            }
        }
    }

测试:

HttpSocket.MakeRequest(new Uri("http://www.google.comhklhlñ"), callbackState =>
    {
        if (callbackState.Exception != null)
            throw callbackState.Exception;
        Console.WriteLine(GetResponseText(callbackState.ResponseStream));
    });
Thread.Sleep(10000);

【问题讨论】:

    标签: c# asynchronous


    【解决方案1】:

    来自Timeout documentation

    Timeout 属性对使用 BeginGetResponse 或 BeginGetRequestStream 方法发出的异步请求没有影响。

    这是因为框架强制您自己处理超时。您应该能够使用example code here,除了将FromAsync 调用返回的Task 传递给ThreadPool.RegisterWaitForSingleObject 方法。


    编辑:

    你需要把注册放在原来的任务上,而不是继续:

    public static void MakeRequest(Uri uri, Action<Stream> responseCallback)
    {
        WebRequest request = WebRequest.Create(uri);
        request.Proxy = null;
        const int TimeoutPeriod = 1000;
    
        Task<WebResponse> t = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
        ThreadPool.RegisterWaitForSingleObject((t as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, TimeoutPeriod, true);
        t.ContinueWith(task =>
        {
            WebResponse response = task.Result;
            Stream responseStream = response.GetResponseStream();
            responseCallback(response.GetResponseStream());
            responseStream.Close();
            response.Close();
        });
    }
    

    这对我有用(如果我将超时持续时间设置得很短,然后点击它,我总是会适当地超时)。

    【讨论】:

    • 我更改了代码,如您在问题中看到的那样,但超时不起作用。我只收到一个 timedOut 为 false 的回调,之后什么都没有发生。
    • 我无法让它工作。我在 main 方法中有一个 thread.sleep。可能是这个问题吗?我更新了帖子,向您展示了我用来测试它的代码。
    • 一开始只抛出一次timedOut false。
    • 我仍然被这个问题困扰@Reed你能帮我吗?您发布的代码对我不起作用。我用我所有的代码(主要包括)更新了这个问题。你能看看吗? stackoverflow.com/questions/7372973/… 感谢您的帮助。
    • @David:我在那里回答:stackoverflow.com/questions/7372973/… 和这里的答案一样,但更明确一点。这项技术很好用……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多