1

I would like to write an Event Handler which triggers a method when website returns some response.

My application fetch response by posting URL's from few websites. Unfortunately at times website return response after some delay(It may take 1 to 5 seconds) and that leads my application to throw an error because next request executes without waiting for previous request to get response.

I can actually put a sleep time after every request that application posts but that doesn't seems to be right way because if I set 5 seconds as sleep time and if suppose website returns response in 1 seconds that makes process to wait for 4 more seconds unnecessarily.

To save some processing time I decide to add Event handlers which should allow application to run next request after we get response for previous request.

So I tried something like this and I can able to call trigger but it is not working the way I want.

My intention is to to create trigger which makes next request to run after getting response to the previous request and at most it can wait 5 second.

Can someone please help me in this, Thanks In advance.

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

//Validating Response after request being posted

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

        ListWithChangedEvent list = new ListWithChangedEvent();

        EventListener listener = new EventListener(list);

        list.Validate(_docNode.InnerHtml);
   }
P J S
  • 170
  • 2
  • 16
  • Have you considered Async and Await? That's probably the de-facto of event driven model given a highly unpredictable latency/bandwidth. – DL Narasimhan Aug 17 '15 at 12:17

2 Answers2

1

HTTP timeouts are a built-in function of most http clients and are the simplest way of requesting web resource with timeout specified.

If you are using WebRequest you can use its timeout property. Here's an example:

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

}

Output:

    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

If you are using WebClient you can also easily configure timeouts. Check this answer out: https://stackoverflow.com/a/6994391/5056245

If you really need to implement timeout at method-calling level, check this out: Implementing a timeout on a function returning a value

If none of those answers work for you, please tell us how are you requesting your web resources.

Community
  • 1
  • 1
balu
  • 121
  • 4
  • Although your solution didn't answer my question exactly but it helped me to use very easiest way to solve my problem. I just used timeout and it is fixed now. Thanks you so much :) – P J S Aug 18 '15 at 08:04
0

You have not specified how you are calling urls. If you use HttpClint (http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client) it can be done as follows:

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
}

There can be many other ways as well. Please post your code for calling urls if this doesn't answer your question.

Deepak Bhatia
  • 1,090
  • 1
  • 8
  • 13