【问题标题】:Request throttling with asynchronous waiting异步等待的请求节流
【发布时间】:2013-03-26 03:58:13
【问题描述】:

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

【问题讨论】:

标签: c# asynchronous throttling


【解决方案1】:

问题在于您的 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 中当前正在执行的线程,那么你根本不应该使用异步方法——你应该同步 em> 延迟,这正是 Thread.Sleep 所做的。

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

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

【讨论】:

  • 哇,真快!我知道我现在哪里出错了,非常感谢。
  • 我之后确实会以 FIFO 方式检查缓存,但该代码已被忽略。关于异步/同步我想你的权利我对这部分有点不清楚,需要做更多的阅读。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
  • 2021-05-17
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多