如何在超时或响应后不断打开WebClient请求

时间:2011-12-23 01:18:06

标签: c# .net asynchronous webclient comet

我正在使用WebClient类和我自己的瘦包装器来通过HTML请求JSON - 我正处于Comet类架构的接收端,因此客户端需要始终保持挂起的请求,这样服务器就可以随意推送到客户端。

我正在尝试确认以下代码是否是正确且安全的方法:

      subscriber = new Action(() =>
      {
          // This function wraps the WebClient 'DownloadStringAsync' method
          client.BeginDownload(this.Path, new AsyncCallback(x =>
          {
              var data = (x.AsyncState as Func<JsonResponse>).EndInvoke(x);
              if (data != null)
              {
                  OnReceive(data, new Uri(this.FullUri));
              }
              subscriber(); // Received data so re-submit request

          }), this.QueryArgs);

          while (client.IsBusy)// As long as busy, no need to re-submit a request
          {
          }
          subscriber(); 
      });

      subscriber();

根据我自己的分析,我认为上述内容将确保客户端在a)收到响应或b)超时时始终重新提交请求。这是否是实现这一目标的可接受方式,还是我错过了更好的做法?以这种方式使用while循环对我来说似乎是不标准的,但是我无法想到创建等待直到循环的任何其他方式。

我还想确保我不会使用此设置泄漏任何资源,因为它可能会或者可能不会每次都调用EndInvoke()吗?

2 个答案:

答案 0 :(得分:1)

我担心递归调用最终会导致堆栈溢出。

如果你运行几秒钟,你会收到堆栈溢出错误......

Action<int> action = null;
action = new Action<int>((i) =>
{
    Console.WriteLine("Hello {0}", i);
    action(i+1);
});
action(1);

我到了12,181。你走了多远? :)

从代码的外观来看,您似乎并不需要调用WebClient的Async方法。事实上,调用直接下载方法可能比你所拥有的紧密循环更有效。

也许是这样的?

var uri = new Uri("http://www.google.com");
var client = new WebClient();
while(true)
{
    try
    {
        var data = client.DownloadData(uri);
        Console.WriteLine("Downloaded {0:N0} bytes.", data.Length);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

答案 1 :(得分:1)

当我过去构建HTTP Streaming库时,我使用了HttpWebRequest类,因为它可以让您获得更多控制权。您可以在this code中找到与Twitter的HTTP Streaming API连接的示例。