C# 使用线程限制每秒的API调用数。睡眠?
和往常一样,我是个不折不扣的人,我相信你会从我的代码和问题中看到这一点。为了练习,我目前正在为一款名为Eve Online的游戏编写一个Xamarin.Android应用程序。那里的人们从行星上开采资源来赚钱。这些地雷必须在不同的时间间隔重置,真正的职业选手最多可以有30个角色来重置。每个角色可以有5颗行星,通常每个行星上至少有2颗地雷(抽取器)。所以可能有300个计时器在运行 在我的应用程序中,您将字符保存在sqlite数据库中,每小时都会有一个intentservice运行API,检查您的时间以及它们是否过期。我就是这样做的:C# 使用线程限制每秒的API调用数。睡眠?,c#,xamarin,C#,Xamarin,和往常一样,我是个不折不扣的人,我相信你会从我的代码和问题中看到这一点。为了练习,我目前正在为一款名为Eve Online的游戏编写一个Xamarin.Android应用程序。那里的人们从行星上开采资源来赚钱。这些地雷必须在不同的时间间隔重置,真正的职业选手最多可以有30个角色来重置。每个角色可以有5颗行星,通常每个行星上至少有2颗地雷(抽取器)。所以可能有300个计时器在运行 在我的应用程序中,您将字符保存在sqlite数据库中,每小时都会有一个intentservice运行API,检查您的时
public async Task PullPlanets(long KeyID, long CharacterID, string VCode, string CharName)
{
XmlReader lesern = XmlReader.Create("https://api.eveonline.com/char/PlanetaryColonies.xml.aspx?keyID=" + KeyID + "&vCode=" + VCode + "&characterID=" + CharacterID);
while (lesern.Read())
{
long planet = 0;
string planetName;
planet = Convert.ToInt64(lesern.GetAttribute("planetID"));
planetName = lesern.GetAttribute("planetName");
if ((planet != 0) && (planetName != null))
{
planets.Add(planet);
planetNames.Add(planetName);
await GetExpirationTimes(CharName, planet, planetName, KeyID, CharacterID, VCode);
}
}
lesern.Close ();
}
public async Task GetExpirationTimes(string CharName, long planetID, string planetName, long KeyID, long CharacterID, string VCode)
{
string planet = planetID.ToString();
XmlReader lesern = XmlReader.Create("https://api.eveonline.com/char/PlanetaryPins.xml.aspx?keyID=" + KeyID + "&vCode=" + VCode + "&characterID=" + CharacterID + "&planetID=" + planet);
while (lesern.Read())
{
string expTime;
expTime = lesern.GetAttribute("expiryTime");
if ((expTime != null) && (expTime != "0001-01-01 00:00:00"))
{
allInfo.Add (new AllInfo (CharName, planetName, Convert.ToDateTime (expTime)));
}
}
lesern.Close ();
SendOrderedBroadcast (stocksIntent, null);
}
}
在此之后,它将时间发送回我的活动,并将它们添加到提取器中。虽然到目前为止,我只能用14个提取器测试2个字符,但它似乎工作得很好。活动中的AlarmManager每小时调用一次服务,并发送通知。当用户打开活动时,它会从服务中提取列表,对其进行排序并显示它。如果这是解决问题的方法,我欢迎大家提供意见
不过,我确实看到了一个问题。如果一个应用每秒超过30次API调用,Eve API就会阻塞。我很确定有30个角色的人会这么做。所以,我想知道,如果某个号码被通过,我是否应该增加一些东西来延迟每个电话?这是我如何调用第一个XML调用的
var table = db.Table<CharsList> ();
foreach (var e in table) {
long KeyIDOut = Convert.ToInt64(e.KeyID);
long CharIDOut = Convert.ToInt64(e.CharacterID);
string VCodeOut = e.VCode.ToString();
string navnOut = e.Name.ToString();
PullPlanets(KeyIDOut, CharIDOut, VCodeOut, navnOut);
}
CheckTimes ();
}
}
该服务是intentservice,不在UI线程上。我想这会使调用速度低于每秒30次,但我从来没有使用过线程。睡觉吧,担心代码中还会发生什么。有没有其他东西可以帮助我不突破极限?这个代码能处理300个提取器吗 我相信你的方法大体上是正确的。我不得不为我正在编写的reddit客户端做类似的事情,除了它们的限制是每秒一次左右 我看到你的设置中唯一的问题是,假设Thread.Sleep在你给它的时间内睡眠。在某些情况下,虚假唤醒是可能的,因此我建议您给它一个较小的值,保存上次访问服务的时间,然后在睡眠呼叫周围放置一个循环,一旦足够的时间过去,该循环就会终止
最后,如果您要在相对较短的时间内启动大量的intent服务,您可能希望有一个带有线程的正常服务来处理该工作-这样,它只需创建一次,但仍然是UI线程的一部分。,
XmlReader
实现了IDisposable
,因此最好在使用块中处理它的使用。谢谢!我会马上实施的!谢谢你的回答和想法。你的解决方案听起来更简单。我意识到睡眠的问题使它变得不准确,我的想法是,即使有打嗝,也可能很容易将其保持在每秒30次以下——如果它是合法的话。我将对这两种方法进行一些认真的测试。我最初是将服务作为服务构建的,但我遇到了很多小问题。现在,从activity或alarmmanager发送意图,然后由intentservice完成所有工作。我没有足够的技能来充分理解这里的利弊。今天我遇到了这个:限制利率的绝佳工具。今晚用200颗行星测试了这个应用程序,它似乎可以正常工作!
if (table.Count > 10) {
foreach (var e in table) {
//start the first characters call
Thread.Sleep(100)