Как сохранить запрос WebClient постоянно открытым после тайм-аута или ответа - PullRequest
0 голосов
/ 23 декабря 2011

Я использую класс WebClient и мою собственную тонкую оболочку вокруг него для запроса JSON через HTML - я нахожусь на приемной стороне архитектуры, подобной 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 ]

1 голос
/ 23 декабря 2011

Когда я в прошлом создавал библиотеки потоковой передачи HTTP, я использовал класс HttpWebRequest, поскольку он дает вам немного больше контроля. Вы можете найти пример в этом коде , который подключается к API потоковой передачи HTTP Twitter.

1 голос
/ 23 декабря 2011

Я был бы обеспокоен тем, что рекурсивные вызовы в конечном итоге вызовут переполнение стека.

Если вы запустите это в течение нескольких секунд, вы получите ошибку переполнения стека ...

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

Я получил 12,181.Как далеко ты зашел?:)

Судя по виду вашего кода, на самом деле вам не нужно вызывать метод Async для WebClient.На самом деле, вызов метода прямой загрузки может быть более эффективным, чем у вас есть замкнутый цикл.

Возможно, что-то вроде этого?

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);
    }
}
...