0

我正在编写一个依赖 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() 似乎不必要地浪费,因为每次调用它都会创建一个新任务。

我觉得可能有一种我不知道的已知方法可以做到这一点?

谢谢,

4

2 回答 2

3

我知道 Task.Delay() 似乎很浪费,但微软员工和MSDN 上的版主在这里推荐

使用 .Sleep() 或 TGH 建议的无限循环会导致程序在等待时变得无响应。如果您希望它在处理队列时响应,您可以使用以下内容:

await Task.Delay(1000);

于 2013-05-31T03:19:24.580 回答
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);

还有你的计时器过程:

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.Exitin a finally。请参阅 Eric Lippert 的Locks and exceptions do not mix的原因。

于 2013-05-31T04:47:11.870 回答