如何让 HttpWebRequest 尽可能同步运行? [英] How can I get HttpWebRequest to behave as synchronously as possible?

查看:28
本文介绍了如何让 HttpWebRequest 尽可能同步运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

总结:这可能吗?

unit test function on ui thread:
- creates a background thread
- starts the thread
- waits for it to complete (function does not exit until it completes!)

background thread:
- opens an http stream 
- reads a url from the web
- terminates

我的怀疑:框架异步地将结果放入一些内部消息队列,因此在 ui 线程的堆栈展开并转到某个 ui 线程函数以泵送堆栈之前,永远不会调用响应回调.

My suspicion: The framework asynchronously puts the result onto some internal message queue and thus the response callback will never be called until the ui thread's stack unwinds and goes to some ui thread function to pump the stack.

完整的故事:

我正在移植一个需要从各种来源创建流的应用程序,其中一个来自一个简单的 http url.我在后台线程上执行此操作,理想情况下,我希望它 100% 同步运行,仅在需要时阻塞(这没问题,因为它在后台线程上).

I am porting an app that requires creating a stream from various sources, one of them being from a simple http url. I am doing this on a background thread, and ideally I would like it to behave 100% synchronously, just block when needed (this is ok since it's on a background thread).

但该框架似乎有点像米老鼠,因为它假设您将在 ui 线程上执行请求,因此它将使编码器不必创建后台线程来执行异步操作.但我可能遗漏了一些东西.

But it seems the framework is a bit mickey mouse in that it assumes you will be doing the request on the ui thread and so it will shield the coder from having to create a background thread to do the asynch operation. But I may be missing something.

我偶然发现了以下文章:http://pieterderycke.wordpress.com/2011/05/23/adding-synchronous-methods-to-webrequest-on-windows-phone-7/,这提出了使 http Web 请求同步的解决方案.但是当它被实施时,我得到了一个 ProtocolViolationException.此后我对代码进行了修改以使用 BeginGetResponse() 而不是 BeginGetRequestStream(),这似乎不再导致异常.

I have stumbled across the following article: http://pieterderycke.wordpress.com/2011/05/23/adding-synchronous-methods-to-webrequest-on-windows-phone-7/, which suggests a solution to make the http web request synchronous. But as it is implemented, I get a ProtocolViolationException. I have since made a modification to the code to use BeginGetResponse() instead of BeginGetRequestStream(), and this seems to no longer cause the exception.

但似乎后台线程现在无限期地阻塞了.在我的 ui 线程上,我循环执行 Thread.Sleep(10),因为我在单元测试函数中,等待我的回调被调用.是否有可能在单元测试函数返回并且 ui 线程有机会泵送消息之前不会调用回调?如果是这样,我有什么办法可以强制它抽水,以便我可以从单元测试例程中中断的地方继续?

But it seems that the background thread now blocks indefinitely. On my ui thread I loop, doing a Thread.Sleep(10) since I am in a unit test function, waiting for my callback to get called. Is it possible that the callback will not be called until unit test function returns and the ui thread has a chance to pump messages? If so, any way I can force it to pump so that I can continue where I left off in the unit test routine?

在上面提到的文章的底部,有一个评论如果你测试你的代码,你会发现在UI线程上执行它会死锁."但我在后台线程上执行它,所以应该没问题吧?

At the bottom of the article mentioned above, a comment is made "If you test your code, you will find that it deadlocks if you execute it on the UI thread." but I am executing it on a background thread, so should be ok right?

msdn 文档仅向您展示如何进行异步调用.他们还提到BeginGetResponse 方法需要一些同步设置任务才能完成"……通常需要几秒钟"……但可能需要 60 秒或更长时间".在 ui 线程上执行这听起来很糟糕.http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx

The msdn docs only show you how to do asynch calls. And they also mention that "The BeginGetResponse method requires some synchronous setup tasks to complete" ... "typically several seconds" ... but "can take 60 seconds or more". This sounds pretty bad to be executed on a ui thread. http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx

请帮忙!

这是我的代码:

using System.Net;
using System.Threading;
using System;
using System.IO;

namespace Blah
{
  // http://pieterderycke.wordpress.com/2011/05/23/adding-synchronous-methods-to-webrequest-on-windows-phone-7/
  // Creates synchronous web requests.
  // Must not be called on UI threads.

  public static class WebRequestExtensions
  {
    public static Stream GetRequestStream(this WebRequest request)
    {
      AutoResetEvent autoResetEvent = new AutoResetEvent(false);

      IAsyncResult asyncResult = null;
      {
        // http://stackoverflow.com/questions/253549/how-do-i-use-httpwebrequest-with-get-method

        if (request.Method == "GET")
        {
          asyncResult = request.BeginGetResponse(
           r => autoResetEvent.Set(), null);
        }
        else
        {
          asyncResult = request.BeginGetRequestStream(
           r => autoResetEvent.Set(), null);
        }
      }

      // Wait until the call is finished
      autoResetEvent.WaitOne();

      return request.EndGetRequestStream(asyncResult);
    }
  }
}

我最近还偶然发现了 http://www.eggheadcafe.com/tutorials/aspnet/91f69224-3da5-4959-9901-c5c717c9b184/making-silverlight-emulate-synchronous-requests.aspx,但这表明一样的问题.似乎在 ui 线程返回堆栈之前我没有得到回调......我可以在某处闻到某种框架消息队列的味道,对吗?

I've also recently stumbled across http://www.eggheadcafe.com/tutorials/aspnet/91f69224-3da5-4959-9901-c5c717c9b184/making-silverlight-emulate-synchronous-requests.aspx, but this exhibits the same problem. Seems that I don't get my callback until the ui thread returns up the stack... I can smell some sort of a framework message queue there somewhere, am I correct?

谢谢

推荐答案

由于 HTTP 响应处理使用 UI 线程,因此阻塞它会阻止请求完成.

As HTTP response processing utilises the UI thread, blocking it will prevent the request from completing.

假设您使用的是 Silverlight 单元测试框架位,您可以将您的测试标记为 [Asynchronous]:

Assuming you are using the Silverlight Unit Testing Framework bits, you can mark your test as [Asynchronous]:

using System;
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Silverlight.Testing;

[TestClass]
public class WebRequestsTests : WorkItemTest
{
    [TestMethod, Asynchronous]
    public void TestWebRequest()
    {
        var webRequest = WebRequest.CreateHttp("http://www.stackoverflow.com");

        webRequest.BeginGetResponse(result =>
        {
            EnqueueCallback(() =>
            {
                WebResponse response = webRequest.EndGetResponse(result);

                // process response 

                TestComplete(); // async test complete 
            });
        }, null);
    }
} 

或者,如果您想使用 Rx(我个人就是这样做的),我最近 发表了一篇博文,内容是在使用 SL 测试框架时如何使基于 Rx 的异步测试更简洁.

Alternatively, if you're looking to use Rx (which I do, personally), I recently did a blog post on how to make Rx-based asynchronous tests cleaner when using the SL testing framework.

这篇关于如何让 HttpWebRequest 尽可能同步运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆