我正在编写一个依赖于JSON API的Windows应用商店应用。 API的提供者要求每秒不超过1个api请求。
所以我创建了一个允许我在阻塞队列上排队请求的类,在后台线程上它会运行一个类似于以下内容的循环:
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)
}
这样,在尝试将另一个请求取消之前,它会等待至少一秒钟。
我发现Thread.Sleep不适用于Windows应用商店。 Task.Delay()似乎不必要地浪费,因为每次调用它都会创建一个新任务。
我觉得可能有一种已知的方法可以做到这一点,我不知道?
谢谢,
答案 0 :(得分:3)
我知道Task.Delay()似乎很浪费,但微软员工和主持人在MSDN here上推荐
使用.Sleep()或像TGH这样的无限循环会导致程序在等待时变得无响应。如果您希望它在处理队列时有响应,您可以使用以下内容:
await Task.Delay(1000);
答案 1 :(得分:0)
如果您希望任务在后台执行,我建议System.Threading.Timer。将其设置为一次性而非周期性计时器,并在每次请求后刷新它。类似的东西:
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);
}
这会产生在一个请求结束和下一个请求开始之间等待一秒的效果。
如果您想要以一秒为间隔执行刻度,则必须确保它们不能重叠。这对Monitor来说很容易。您需要一个锁定对象,并使您的计时器成为定期计时器:
object timerLock = new object();
// initialize periodic timer
myTimer = new Timer(TimerProc, null, 1000, 1000);
你的计时器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);
}
请注意,我没有在Monitor.Exit
中执行finally
。请参阅Eric Lippert的Locks and exceptions do not mix了解原因。