C# 发出多个Http请求时,缓冲区大小不足或队列已满

C# 发出多个Http请求时,缓冲区大小不足或队列已满,c#,concurrency,wikipedia-api,C#,Concurrency,Wikipedia Api,我目前正试图使用维基百科的公共API从维基百科中获取大量关于视频游戏的数据。我已经找到了一些方法。我目前可以获得与他们相关的文章标题所需的所有pageid。但我需要得到它们的唯一标识符(Qxxxx,其中x是数字),这需要相当长的时间……可能是因为我必须对每个标题进行单个查询(有22031个),或者因为我不理解维基百科的查询 所以我想“为什么不一次做多个查询呢?”于是我开始研究这个问题,但我在标题中遇到了这个问题。程序运行一段时间(通常为3-4分钟)后,大约一分钟过去,然后应用程序崩溃,标题中出现

我目前正试图使用维基百科的公共API从维基百科中获取大量关于视频游戏的数据。我已经找到了一些方法。我目前可以获得与他们相关的文章
标题
所需的所有
pageid
。但我需要得到它们的唯一标识符(Qxxxx,其中x是数字),这需要相当长的时间……可能是因为我必须对每个标题进行单个查询(有22031个),或者因为我不理解维基百科的查询

所以我想“为什么不一次做多个查询呢?”于是我开始研究这个问题,但我在标题中遇到了这个问题。程序运行一段时间(通常为3-4分钟)后,大约一分钟过去,然后应用程序崩溃,标题中出现错误。我认为这是因为我的方法很糟糕:

ConcurrentBag<Entry> entrybag = new ConcurrentBag<Entry>(entries);
Console.WriteLine("Getting Wikibase Item Ids...");
Parallel.ForEach<Entry>(entrybag, (entry) =>
{
    entry.WikibaseItemId = GetWikibaseItemId(entry).Result;
});

也许有人能帮忙吗?我是否只需要更改查询方式或其他方式?

从一个进程并行启动大约22000个http请求实在是太多了。如果您的计算机有无限的资源和internet连接带宽,这将接近拒绝服务攻击

您看到的是TCP/IP端口耗尽或队列争用。要解决此问题,请将数组分成更小的块进行处理,例如,获取10个项目,并行处理这些项目,然后获取下一个10个项目,依此类推

特别是要连续处理请求:

对阅读请求没有严格的限制,但我们要求您考虑周到,尽量不要关闭网站。大多数系统管理员保留在您危及其站点稳定性时随意阻止您的权利

如果您以串联方式而不是并行方式提出请求(即,在发送新请求之前等待一个请求完成,这样您就永远不会同时提出多个请求),那么您肯定不会有问题


一定要检查他们的API服务条款,以了解并行请求是否符合要求以及有多少符合要求。

将并发运行的查询数量限制在合理的数量,如10,而不是22。崩溃是因为服务器不喜欢查询。手动尝试将查询放入网页的URL中。您的应用程序仅在3-4分钟后超时。如果你得到了文章的标题,你也应该能够同时得到URL。然后按URL检索文章。@dlatikay我会试试这个@Tgr随机词。。?一点也不。我将它们替换为与Wikipedia查询字符串一起使用的单词。不要这么居高临下。你的问题是你没有对标题进行百分比编码,但这是初学者常见的错误(尽管阅读文档或示例代码可以避免)。你试图解决这个问题的方式是。。。创造性的它在大多数情况下都不起作用,在某些情况下会以意想不到的方式失火(例如和是不同的事情)。是的,我试着通读它们,看看我能做些什么,但你是对的。这接近DDOS攻击lol。我更改了它,现在并行运行的请求更少了。但我真的应该改变它,让它像你说的那样一次获得多个ID。@Tgr在评论中指出,有些参数是多值参数<代码>标题
。因此,甚至可以在一个请求中组合查询多个标题。
async static Task<String> GetWikibaseItemId(Entry entry)
{
    using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
    {
        client.BaseAddress = new Uri("https://en.wikipedia.org/w/api.php");
        entry.Title.Replace("+", "Plus");
        entry.Title.Replace("&", "and");
        String queryString = "?action=query&prop=pageprops&ppprop=wikibase_item&format=json&redirects=1&titles=" + entry.Title;
        HttpResponseMessage response = await client.GetAsync(queryString);

        response.EnsureSuccessStatusCode();

        String result = response.Content.ReadAsStringAsync().Result;
        dynamic deserialized = JsonConvert.DeserializeObject(result);
        String data = deserialized.ToString();
        try
        {
            if (data.Contains("wikibase_item"))
            {
                return deserialized["query"]["pages"]["" + entry.PageId + ""]["pageprops"]["wikibase_item"].ToString();
            }
            else
            {
                return "NONE";
            }
        }
        catch (RuntimeBinderException)
        {
            return "NULL";
        }
        catch (Exception)
        {
            return "ERROR";
        }
    }
}
public class Entry
{
    public EntryCategory Category { get; set; }
    public int PageId { get; set; }
    public String Title { get; set; }
    public String WikibaseItemId { get; set; }
}