【发布时间】:2017-05-20 14:14:35
【问题描述】:
我有一个控制台应用程序,它使用多个线程来处理项目列表。所有这些项目都需要访问一个 API,我不想每秒向该 API 发出超过 1 个请求。
所以我有一个执行 API 请求的类
Public Class apiRequest
Property lastRequest as date = now()
function doRequest()
'check if we can make a request
if Now.Substract(lastRequest).Seconds > 1 then
lastRequest = now()
'Do request [...]
end if
end function
End Class
我有主程序
property apiRequester as new apiRequest
sub main
'start multiple threads (addressOf threadFunction)[...]
end sub
sub threadFunction()
dim data as string = apirequester.doRequest() 'Call the api request
end sub
但是如果两个线程同时执行一个请求会发生什么,它们都通过了秒检查,因为它们首先执行了这行代码
if Now.Substract(lastRequest).Seconds > 1 then
在他们到达这条线之前
lastRequest = now()
如何使 apiRequest 函数每秒只有 1 个请求?
解决方案
我使用SyncLock找到了以下解决方案。
Private locker As New Object
Private lastRequest as date = now()
function doRequest()
SyncLock locker
if Now.Substract(lastRequest).Seconds > 1 then
lastRequest = now()
end if
End Synclock
end function
这与 Monitor.Enter 中的 Monitor.Enter、Monitor.Exit answer 几乎相同,除了 lock 和 SyncLock 将 Exit 方法包装在 try...finally 块中(在 Visual Basic 中为 Try...Finally)以确保监视器被释放(正如 Alex B 在 cmets 中指出的那样)
【问题讨论】:
-
另一种方法是将项目添加到 ConcurrentQueue 并在计时器滴答时将它们出列。这样,您可以随时创建请求,但它们将按照您设置的速率提交,并且不需要锁定任何内容。
标签: .net vb.net multithreading