1

我在我的应用程序中实现了一些请求限制。它基于使用 MemoryCache 和根据限制过期的项目。基本上我尝试检索一个缓存项目,如果它不存在我继续发出请求,如果是他们我检查最后一个请求并锻炼下一个可用时间我可以发出请求。我的问题在于我必须等待提出请求。

//This is a shortened version of what im doing, but the includes the required code

public void ThrottleRequest(string webservice)
{
    if (cache.TryGet(webservice))
    {
          var timeToWait = GetTimeToWaitFromSomewhere(); 
          Wait(timeToWait);
    }
}

public async void Wait(TimeSpan timeToWait)
{
     await Task.Delay(timeToWait); //This doesnt work
     Thread.Sleep(timeToWait); //This works
}

问题在于等待方法。如果我使用 thread.sleep 数字匹配并且请求被正确限制(即每秒 1 个请求),但我永远不想在生产环境中使用它。那么在这里异步等待的正确方法是什么?我是在滥用 API 还是什么?

4

1 回答 1

5

问题是你的Wait方法有一个返回类型void——你基本上是在说,“开始等待,我会继续前进,忽略等待!”

你通常有它:

public async Task ThrottleRequest(string webservice)
{
    if (cache.TryGet(webservice))
    {
        var timeToWait = GetTimeToWaitFromSomewhere(); 
        await Wait(timeToWait);
    }
}

public async Task Wait(TimeSpan timeToWait)
{
     await Task.Delay(timeToWait);
}

虽然在这一点上,你的Wait方法是没有意义的,你最好写:

public async Task ThrottleRequest(string webservice)
{
    if (cache.TryGet(webservice))
    {
        var timeToWait = GetTimeToWaitFromSomewhere(); 
        await Task.Delay(timeToWait);
    }
}

请注意,我已将您的ThrottleRequest方法更改为异步并返回Task。目前尚不清楚您希望调用Wait自行实现什么,但如果您尝试引入异步,您需要非常清楚自己在做什么 - 通常调用异步方法的方法将是异步。

如果您真的只是想暂停当前正在执行的线程ThrottleRequest,那么您根本不应该使用异步方法 - 您想要同步延迟,这正是这样Thread.Sleep做的。

我强烈怀疑您目前对您的代码在同步或异步方面的用途并不完全清楚。我会从代码本身退后一步,弄清楚你实际期望它如何工作(例如,想想你希望线程模型是什么),然后回到键盘。

还要考虑在延迟发生后,您不会再次检查缓存 - 这意味着如果 20 个不同的线程每个都同时进入您的方法,它们最终都会访问Web 服务,而不是只有其中一个在做所以其余的使用缓存的结果。

于 2013-03-25T19:48:34.857 回答