请求使用异步等待进行限制

时间:2013-03-25 19:46:19

标签: c# asynchronous throttling

我已在我的应用中实施了一些请求限制。它基于使用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还是什么?

1 个答案:

答案 0 :(得分: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服务,而不是只有其中一个使用缓存结果。