创建数百万个任务以同时从api获取每个项目的数据

时间:2017-02-23 08:45:54

标签: c# optimization concurrency async-await task

我有一个包含数百万条记录的数据库表。 对于每条记录,我需要通过API获取一些额外的数据。

所以我试图利用Task和async-await模式在C#中利用并发性。 对于我创建Task的每条记录,我在其中使用HttpClient调用api。

不幸的是,这会产生内存不足的异常。

IEnumerable<Task<Item>> tasks =
            items.Select(
                async i => await GetItemDataFromApi(i));

            var result = await Task.WhenAll(tasks);

这是一种方法吗?我应该创建一个获取每条记录数据的任务吗?

2 个答案:

答案 0 :(得分:1)

在Task.WhenAll中等待一百万个Task对象至少需要一个包含这些数百万个对象的数组。除了内存消耗之外,它还会增加系统管理所有这些对象的负担。一些改进的想法:

  • 创建批次 - 在一个管理类中同时处理多行(例如千行)

  • 不要为每个任务实例化HttpClient。可以同时使用相同的HttpClient对象,并有助于限制套接字的资源使用。

  • 限制Web API的使用 - 我无法想象如果他们的服务器在短时间内被数百万个请求击中,任何人都会感到高兴。

答案 1 :(得分:1)

Web服务器有一个限制,我认为你需要做的事情:

  1. 创建Queue<DBRecord>
  2. 创建一个线程(任务)以将项目排队到此队列
  3. 创建10-20个线程(任务)以使项目出列并通过HttpClient开始调用此WebAPI
  4. 10-20个线程将结果存储到另一个结果数组中。
  5. 一旦结果数组足够大,就需要将它存储到数据库或者你想用它做什么。
  6. 提示:

    • 队列和结果应该是线程安全的,或者您可以使用Mutex或Semaphore保护它们。
    • 您无法在计算机上启动大量线程(任务),因为每个线程都需要内存来跟踪其堆栈。所以你将结束记忆。