Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在多线程环境中实现有限的API调用?_C#_Multithreading_Amazon Web Services_Rate Limiting - Fatal编程技术网

C# 如何在多线程环境中实现有限的API调用?

C# 如何在多线程环境中实现有限的API调用?,c#,multithreading,amazon-web-services,rate-limiting,C#,Multithreading,Amazon Web Services,Rate Limiting,我有很多请求要发送到服务器(Amazon产品广告API),但是该服务器不允许我每秒发送超过1个请求。 我正在寻找一个基于C#能力的免费解决方案 我试着这样编码: public static WebResponse Request(Dictionary<string, string> parameters) { var response = LaunchRequest(parameters); Sleep(1000); return response; } 它似乎在大部分

我有很多请求要发送到服务器(Amazon产品广告API),但是该服务器不允许我每秒发送超过1个请求。
我正在寻找一个基于C#能力的免费解决方案

我试着这样编码:

public static WebResponse Request(Dictionary<string, string> parameters) {
  var response = LaunchRequest(parameters);
  Sleep(1000);
  return response;
}
它似乎在大部分时间都能工作,但有时,我的“LaunchRequest”方法几乎同时启动

编辑2: 以下是日志结果,箭头显示了少于1秒的调用:

Request: 09:52:50.230  - Thread 22
Request: 09:52:48.830  - Thread 5
Request: 09:52:47.468  - Thread 10 <---
Request: 09:52:47.331  - Thread 13 <---
Request: 09:52:45.971  - Thread 12
Request: 09:52:44.767  - Thread 11
Request: 09:52:43.230  - Thread 5
Request: 09:52:30.546  - Thread 21 <--- 
Request: 09:52:30.357  - Thread 20 <---
Request: 09:52:29.232  - Thread 13
Request: 09:52:27.908  - Thread 11
Request: 09:52:26.471  - Thread 5
Request: 09:52:25.138  - Thread 11
Request: 09:52:23.835  - Thread 12
请求:09:52:50.230-线程22
请求:09:52:48.830-螺纹5
请求:09:52:47.468-线程10创建一个SQS队列。
在控制器中,将数据放入队列。
创建一个.net服务,该服务将轮询队列并逐个处理消息,确保在任何给定时间只发送一条消息

UPD不知道如果你不喜欢AWS服务,为什么要将帖子标记为AWS,但仍然是

代替SQS,您可以使用任何可用的不同队列,例如MSMQ、RabbitMQ等。成本将取决于您自己安装和维护这些队列的需要

绝对最坏情况下,使用C#中的
ConcurrentQueue
类型,并运行一个后台线程,该线程将从该队列弹出。这将确保一次只处理一条消息。但是,此解决方案没有弹性,因为应用程序池回收将擦除您的数据。

创建SQS队列。 在控制器中,将数据放入队列。 创建一个.net服务,该服务将轮询队列并逐个处理消息,确保在任何给定时间只发送一条消息

UPD不知道如果你不喜欢AWS服务,为什么要将帖子标记为AWS,但仍然是

代替SQS,您可以使用任何可用的不同队列,例如MSMQ、RabbitMQ等。成本将取决于您自己安装和维护这些队列的需要


绝对最坏情况下,使用C#中的
ConcurrentQueue
类型,并运行一个后台线程,该线程将从该队列弹出。这将确保一次只处理一条消息。但是,此解决方案没有弹性,因为应用程序池回收将擦除您的数据。

将上次通话的详细信息存储在会话或局部变量中。如果有电话的话,你可以打电话给sleep

public static WebResponse Request(Dictionary<string, string> parameters) 
{
    lock (thisLock)
    {
        string lastCalled = Session["LastCalledTime"] as string;
        if (!string.IsNullOrEmpty(lastCalled) && DateTime.Parse(lastCalled) >= DateTime.Now.AddSeconds(-1))
        {
            Sleep(1000);
        }
        var response = LaunchRequest(parameters);
        Session["LastCalledTime"] = DateTime.Now.ToString("O");
    }

    return response;
 }
publicstaticwebresponse请求(字典参数)
{
锁(这个锁)
{
字符串lastCalled=会话[“LastCalledTime”]作为字符串;
如果(!string.IsNullOrEmpty(lastCalled)&&DateTime.Parse(lastCalled)>=DateTime.Now.AddSeconds(-1))
{
睡眠(1000);
}
var响应=启动请求(参数);
Session[“LastCalledTime”]=DateTime.Now.ToString(“O”);
}
返回响应;
}

添加了锁以使其线程安全,如突出显示的。

在会话或局部变量中存储上次调用的详细信息。如果有电话的话,你可以打电话给sleep

public static WebResponse Request(Dictionary<string, string> parameters) 
{
    lock (thisLock)
    {
        string lastCalled = Session["LastCalledTime"] as string;
        if (!string.IsNullOrEmpty(lastCalled) && DateTime.Parse(lastCalled) >= DateTime.Now.AddSeconds(-1))
        {
            Sleep(1000);
        }
        var response = LaunchRequest(parameters);
        Session["LastCalledTime"] = DateTime.Now.ToString("O");
    }

    return response;
 }
publicstaticwebresponse请求(字典参数)
{
锁(这个锁)
{
字符串lastCalled=会话[“LastCalledTime”]作为字符串;
如果(!string.IsNullOrEmpty(lastCalled)&&DateTime.Parse(lastCalled)>=DateTime.Now.AddSeconds(-1))
{
睡眠(1000);
}
var响应=启动请求(参数);
Session[“LastCalledTime”]=DateTime.Now.ToString(“O”);
}
返回响应;
}


添加了锁以使其线程安全,如所突出显示的。

我正在寻找免费解决方案。我真的认为这种事情在C#Lawi是可行的。这是正确的答案。你没有在问题的任何地方提到解决方案必须免费的要求。此外,您用AWS标记了这个问题,这就是您用AWS解决这个问题的方法。您是否查看过SQS以验证您的使用是否会超过免费层?好吧,我必须明确表示我想要一个免费的解决方案。我编辑我的帖子是为了添加这个规范。@Lawi当你说“免费”时,你是什么意思?当然,这在c#…@zaitsman是可行的,我不想要任何金钱成本。我尝试了“锁”,但这不起作用…我正在寻找一个免费的解决方案。我真的认为这种事情在C#Lawi是可行的。这是正确的答案。你没有在问题的任何地方提到解决方案必须免费的要求。此外,您用AWS标记了这个问题,这就是您用AWS解决这个问题的方法。您是否查看过SQS以验证您的使用是否会超过免费层?好吧,我必须明确表示我想要一个免费的解决方案。我编辑我的帖子是为了添加这个规范。@Lawi当你说“免费”时,你是什么意思?当然,这在c#…@zaitsman是可行的,我不想要任何金钱成本。我尝试了“锁定”,但这不起作用……而且这可能更具可读性:我用一个新的实现使用锁定编辑了我的帖子,但仍然存在一个问题。此外,这可能更具可读性:我用一个新的实现使用锁定编辑了我的帖子,但是仍然有一个问题。@trailmax:我想它已经解决了。那么为什么要从锁中排除
LaunchRequest
?另外,当我们知道在任何情况下都需要在请求后等待一秒钟时,使用会话有什么意义?只需执行
LaunchRequest();睡眠(1000)我用一个新的实现编辑了我的文章,使用了锁,但仍然存在一个问题。@trailmax LaunchRequest不需要锁。这是对外部资源的调用,可能会消耗更多的时间。LaunchRequest也必须处于锁定状态,因为没有它,您将有竞争条件。@trailmax:我认为它是固定的。那么为什么要从锁定中排除
LaunchRequest
?另外,当我们知道在任何情况下都需要在请求后等待一秒钟时,使用会话有什么意义?只需执行
LaunchRequest();睡眠(1000)我用一个新的实现编辑了我的文章,使用了锁,但仍然存在一个问题。@trailmax LaunchRequest不需要锁。它是对外部资源的调用,可以消耗m
public static WebResponse Request(Dictionary<string, string> parameters) 
{
    lock (thisLock)
    {
        string lastCalled = Session["LastCalledTime"] as string;
        if (!string.IsNullOrEmpty(lastCalled) && DateTime.Parse(lastCalled) >= DateTime.Now.AddSeconds(-1))
        {
            Sleep(1000);
        }
        var response = LaunchRequest(parameters);
        Session["LastCalledTime"] = DateTime.Now.ToString("O");
    }

    return response;
 }