【问题标题】:Make application to wait after posting request till Website returns response using Event Handlers使应用程序在发布请求后等待,直到网站使用事件处理程序返回响应
【发布时间】:2015-11-07 14:51:20
【问题描述】:

我想写一个事件处理程序,当网站返回一些响应时触发一个方法。

我的应用程序通过从几个网站发布 URL 来获取响应。不幸的是,有时网站会在一些延迟后返回响应(可能需要 1 到 5 秒),这会导致我的应用程序抛出错误,因为下一个请求会在没有等待上一个请求得到响应的情况下执行。

我实际上可以在应用程序发布的每个请求之后设置一个睡眠时间,但这似乎不是正确的方式,因为如果我将 5 秒设置为睡眠时间,并且假设网站在 1 秒内返回响应,这会使进程等待不必要地多花 4 秒。

为了节省一些处理时间,我决定添加事件处理程序,它应该允许应用程序在我们获得上一个请求的响应后运行下一个请求。

所以我尝试了这样的事情,我可以调用触发器,但它没有按我想要的方式工作。

我的目的是创建一个触发器,在收到对上一个请求的响应后运行下一个请求,最多可以等待 5 秒。

谁能帮帮我,在此先感谢。

public delegate void ChangedEventHandler(string response);

public class ListWithChangedEvent : EventArgs
{
    public event ChangedEventHandler Changed;

    protected virtual void OnChanged(string response) 
    {
        if (Changed != null)
         {
             Changed(response);
         }
      }

  public void Validate(string response) 
  {
      OnChanged(response);
  }
}

public class EventListener 
{
  private ListWithChangedEvent _list;

  public EventListener(ListWithChangedEvent list) 
  {
      _list = list;
      _list.Changed += new ChangedEventHandler(ListChanged);
  }

  private void ListChanged(string response) 
  {
      if (!response.IsEmpty())
      {
          return;
      }
  }
}

//发布请求后验证响应

private void _postRequestAndParseResponse()
    {
       _performPostRequest(_returnTailPart(_urls.CommonUrl), argumentsList);

        ListWithChangedEvent list = new ListWithChangedEvent();

        EventListener listener = new EventListener(list);

        list.Validate(_docNode.InnerHtml);
   }

【问题讨论】:

  • 你考虑过 Async 和 Await 吗?鉴于高度不可预测的延迟/带宽,这可能是事实上的事件驱动模型。

标签: c# asp.net .net c#-4.0 event-handling


【解决方案1】:

HTTP 超时是大多数 http 客户端的内置功能,是请求指定超时的 Web 资源的最简单方法。

如果您使用的是 WebRequest,您可以使用它的 timeout 属性。这是一个例子:

public void Test()
{
    const int timeoutMs = 5000;
    sw.Start();
    RequestWithTimeout("https://google.com", timeoutMs);
    RequestWithTimeout("http://deelay.me/7000/google.com", timeoutMs);
    RequestWithTimeout("http://thisurelydoesnnotexist.com", timeoutMs);
    RequestWithTimeout("http://google.com", timeoutMs);
}

private void RequestWithTimeout(string url, int timeoutMs)
{
    try
    {
        Log("Webrequest at " + url + " starting");
        WebRequest req = WebRequest.Create(url);
        req.Timeout = timeoutMs;                                
        var response = req.GetResponse();                
        Log("Webrequest at " + url + " finished");
    }
    catch (WebException webException)
    {
        Log("WebRequest failed: " + webException.Status);
    }
    catch (Exception ex)
    {
        Log(ex.ToString());
    }

}

输出:

    0ms | Webrequest at https://google.com starting
  169ms | Webrequest at https://google.com finished
  170ms | Webrequest at http://deelay.me/7000/google.com starting
 5186ms | WebRequest failed: Timeout
 5186ms | Webrequest at http://thisurelydoesnnotexist.com starting
 5247ms | WebRequest failed: NameResolutionFailure
 5247ms | Webrequest at http://google.com starting
 5311ms | Webrequest at http://google.com finished

如果您使用的是 WebClient,您还可以轻松配置超时。看看这个答案:https://stackoverflow.com/a/6994391/5056245

如果您确实需要在方法调用级别实现超时,请查看以下内容: Implementing a timeout on a function returning a value

如果这些答案都不适合您,请告诉我们您是如何请求网络资源的。

【讨论】:

  • 虽然您的解决方案没有准确回答我的问题,但它帮助我使用了最简单的方法来解决我的问题。我刚刚使用了超时,现在已修复。非常感谢你:)
【解决方案2】:

您尚未指定如何调用 url。如果你使用 HttpClint (http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client) 可以这样做:

using(var client = new HttpClient())
{
    var task = client.PostAsync(url1, ..., ...);

    if(!task.wait(5000))
    {
        //task not completed in specified interval (5 sec), take action accordingly.
    }
    else
    {
        // task completed within 5 second, take action accordingly, you can access the response using task.Result
    }

    // Continue with other urls as needed
}

还有很多其他的方法。如果这不能回答您的问题,请发布您的调用网址代码。

【讨论】:

  • 感谢您的回答
猜你喜欢
  • 2021-01-23
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
相关资源
最近更新 更多