gpt4 book ai didi

c# - Throttle - 最多每 N 毫秒调用一个函数?

转载 作者:行者123 更新时间:2023-11-30 14:46:05 25 4
gpt4 key购买 nike

如果过于频繁地调用以下函数中的函数 callWebServiceAsync 将被拒绝。完成可能需要几毫秒到一分钟。

F#

let doWorkAsync p = async { // doWorkAsync will be called many times
....
let! ret = callWebServiceAsync p' // need to be throttled, high volumn of requestion in a short time will cause blocking
....
let ret' = process ret
ret'
}

C#

async Task<T> DoWorkAsync(S p) // DoWorkAsync will be called many times
{
....
ret = await CallWebServiceAsync(...); // need to be throttled, high volumn of requestion in a short time will cause blocking
....
return Process(ret);
}

如何限制调用频率?我不确定他们是如何检测调用的,所以最好均匀地调用函数(没有突发请求)。

最佳答案

我的第一 react 是使用 MailboxProcessor .这就是您通常强制所有调用通过单个网关的方式。

下面是一个 throttle 函数,每个时间跨度最多返回一次异步延续。高水平,它

  1. 从消息队列中获取调用请求 (inbox.Receive)。此请求包含返回结果的 channel 。
  2. 检查上次运行是否需要延迟,然后休眠
  3. 记下当前调用的开始时间(请注意,如果您想根据调用的结束时间进行节流,则可以交换此步骤和第 4 步)
  4. 触发调用者(chan.Reply)
  5. 循环获取另一个请求

代码如下

let createThrottler (delay: TimeSpan) =
MailboxProcessor.Start(fun inbox ->
let rec loop (lastCallTime: DateTime option) =
async {
let! (chan: AsyncReplyChannel<_>) = inbox.Receive()
let sleepTime =
match lastCallTime with
| None -> 0
| Some time -> int((time - DateTime.Now + delay).TotalMilliseconds)
if sleepTime > 0 then
do! Async.Sleep sleepTime
let lastCallTime = DateTime.Now
chan.Reply()
return! loop(Some lastCallTime)
}
loop None)

然后你可以像这样使用它:

[<EntryPoint>]
let main argv =
// Dummy implementation of callWebServiceAsync
let sw = Stopwatch.StartNew()
let callWebServiceAsync i =
async {
printfn "Start %d %d" i sw.ElapsedMilliseconds
do! Async.Sleep(100)
printfn "End %d %d" i sw.ElapsedMilliseconds
return i
}

// Create a throttler MailboxProcessor and then the throttled function from that.
let webServiceThrottler = createThrottler (TimeSpan.FromSeconds 1.)
let callWebServiceAsyncThrottled i =
async {
do! webServiceThrottler.PostAndAsyncReply(id)
return! callWebServiceAsync i
}

// Some tests
Async.Start(async { let! i = callWebServiceAsyncThrottled 0
printfn "0 returned %d" i
let! i = callWebServiceAsyncThrottled 1
printfn "1 returned %d" i
let! i = callWebServiceAsyncThrottled 2
printfn "2 returned %d" i })
Async.Start(callWebServiceAsyncThrottled 3 |> Async.Ignore)
Async.Start(callWebServiceAsyncThrottled 4 |> Async.Ignore)
Async.Start(callWebServiceAsyncThrottled 5 |> Async.Ignore)
Async.Start(callWebServiceAsyncThrottled 6 |> Async.Ignore)
Console.ReadLine() |> ignore
0

如果您运行此程序,您会发现它会根据需要限制对该服务的调用,无论您是并行运行还是串行运行或两者兼而有之。

关于c# - Throttle - 最多每 N 毫秒调用一个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50660579/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com