Reputation: 1078
I'm writing a Windows Store app that will rely on a JSON api. The provider of the API asks that no more than 1 api request is made per second.
So I created a class that would allow me to queue requests on a blocking queue, and on a background thread it would run a loop that resembles the following:
Loop
{
// this will block until a request is added to the queue
MyRequest = Queue.Take()
// Create task to make the api request here.
Thread.Sleep(1000)
}
This way, it would wait at least one second before trying to Dequeue another request.
I've found that Thread.Sleep is not available for windows store apps. Task.Delay() seems unnecessarily wasteful, since it will create a new task each time it is called.
I feel like there is probably a known way to do this that I'm not aware of?
Thanks,
Upvotes: 0
Views: 127
Reputation: 133975
If you want the task to execute in the background, I would suggest a System.Threading.Timer. Set it up as a one-shot rather than a periodic timer, and refresh it after every request. Something like:
System.Threading.Timer myTimer;
// initialize timer
myTimer = new Timer(TimerProc, null, 1000, Timeout.Infinite);
void TimerProc(object state)
{
// do request here
// then reset the timer
myTimer.Change(1000, Timeout.Infinite);
}
That will have the effect of waiting one second between when one request ends and the next one starts.
If you want ticks to execute on one-second intervals, you have to make sure that they can't overlap. That's easy enough with Monitor. You'll need a lock object, and to make your timer an periodic timer:
object timerLock = new object();
// initialize periodic timer
myTimer = new Timer(TimerProc, null, 1000, 1000);
And your timer proc:
void TimerProc(object state)
{
if (!Monitor.TryEnter(timerLock))
{
// a request is currently being processed
return;
}
try
{
// do request here
}
catch (expected exceptions)
{
}
Monitor.Exit(timerLock);
}
Note that I don't do the Monitor.Exit
in a finally
. See Eric Lippert's Locks and exceptions do not mix for the reasons why.
Upvotes: 0
Reputation: 2241
I know Task.Delay() seems wasteful, but it's recommended by a Microsoft Employee and moderator on MSDN here
Using .Sleep() or an infinite loop like TGH suggests would cause the program to become unresponsive while it waits. If you want it to be responsive while processing your queue, you'd use something like this:
await Task.Delay(1000);
Upvotes: 2