9

I have an ASP.Net MVC 4 application that periodically calls an external API for information (resource). This resource has a rate limiter for the account (meaning other apps use the same pool and may hit the limit). When this limit is hit, It will send back a HTTP Status Code 429 with a header of "Retry-After" in seconds (lets say 25 seconds).

If my app gets this response, I will then need to delay execution for 25 Seconds and retry. First off, let me say that the method that this code is running under is an ASP.Net 4.5 Async method. For this, I was thinking about using the System.Threading.Thread.Sleep(25000) Now, I really don't like to use this, is there a better way of doing this?

I have to say that I apologize for this open ended question, but I couldn't find anything on the proper way of delay execution (while keeping things async and making sure that we don't run out of threads)

Update: Would the following code be better for the delay?

  await Task.Run(() => Thread.Sleep(10000))
i3arnon
  • 113,022
  • 33
  • 324
  • 344
hjavaher
  • 2,589
  • 3
  • 30
  • 52
  • 25s is a lot of time. What if the client browser running your web app times out meanwhile? – noseratio Feb 06 '14 at 08:26
  • Sorry for the delay, I'm not sure to be honest, the max delay is 30 seconds and this all happens during an ajax call so I'm not sure how that works. I will look into this – hjavaher Feb 06 '14 at 23:18
  • 1
    To take the AJAX idea further, check this: [Long Running Background Tasks in Asp.Net MVC3](http://alandjackson.wordpress.com/2012/04/11/long-running-background-tasks-in-asp-net-mvc3). – noseratio Feb 12 '14 at 07:03

4 Answers4

16

You shouldn't use Thread.Sleep because it blocks the thread for that amount of time so your server is less scalable. You should instead use Task.Delay which waits asynchronously without blocking a thread:

await Task.Delay(10000)

Task.Delay uses a Timer internally to accomplish that. For more info: Thread.Sleep vs Task.Delay?

Community
  • 1
  • 1
i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • Thank you for that, I've seen the Task.Delay before and don't know why I didn't go that route to begin with. Noseratio brought up a good point, doesn't 25 - 30 seconds make the browser timeout? – hjavaher Feb 06 '14 at 23:22
  • I'm not sure, maybe you can control that timeout or cache the api results in your server or even delay it from the client like he suggested. – i3arnon Feb 07 '14 at 10:42
7

I recommend you use the Transient Fault Handling Block, which was designed specifically for this kind of scenario.

However, if you want to implement your own retry mechanism, Task.Delay is a better choice than Task.Run+Thread.Sleep.

Community
  • 1
  • 1
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • I've thought about using the Transient Fault Handling, but to be honest, I consider myself a beginner and couldn't figure out how to configure it correctly – hjavaher Feb 06 '14 at 23:20
3

25 seconds is a lot of time to wait for the response on the client-side, while you're delaying the 3rd party API request on the server. It might be a good idea to initiate the retry from the client AJAX code, if you really need this data/resource on the client-side. Then you wouldn't have to organize the wait on the server-side at all.

noseratio
  • 59,932
  • 34
  • 208
  • 486
1

Since it appears you are doing this in ASP.NET, then you could use Quartz.net to schedule jobs and change when a job needs to execute again (say 25 seconds). Their website: Quartz Enterprise Scheduler .NET.

A previous question on using Quartz.net in ASP.NET is located here. Hope that helps you out.

Community
  • 1
  • 1
FrankO
  • 2,522
  • 6
  • 24
  • 34
  • That is definitely interesting, I will lookinto this. – hjavaher Feb 06 '14 at 23:19
  • I would hesitate any manual thread manipulation within the ASP.NET process unless you have an in depth knowledge of the subject. Keep in mind that IIS can shut down the process at any time it feels necessary. – FrankO Feb 07 '14 at 02:45