为什么 Google 使用 DownloadStringAsync(Uri, Object) C# 进行地理编码需要这么长时间

Why is Google Geocoding taking so long using DownloadStringAsync(Uri, Object) C#

我们有一个数据 table,其中包含我正在尝试进行地理编码的地址。

然后我们循环遍历数据table 行,使用WebClient.downloadStringAsync(Uri, Object) 向Google 地理编码发送api 请求,并对数据table.

所有线程完成后,我们需要更新数据库。

为此,我们使用 Task.Factory.StartNew 函数并跟踪它们以等待所有任务完成。

我们看到 8000 个地址在 10 多分钟内完成。

这是正常现象还是有更好的方法?

如有任何建议,我们将不胜感激。

精简后的代码供参考:

         DataTable dataTable = new DataTable();
            String url = "https://maps.googleapis.com/maps/api/geocode/json?address={0}&key={1}";
            List<Task> tasks = new List<Task>();
            int i = 0;
            foreach (DataRow row in dataTable.Rows) //8000 + rows
            {
            Uri uriWithAddress = new Uri(String.Format(url, new[] {
                "full_address",
                "apiKey"
            }));
            tasks.Add(Task.Factory.StartNew(() => {
                using (System.Net.WebClient client = new System.Net.WebClient())
                {

                     client.DownloadStringCompleted += (o, a) =>
                     {
                         //when finished... do some work like lock datatable
                         //and change some values etc
                     }; 
                     client.DownloadStringAsync(uriWithAddress, i);
                     i++;
                }
            }));
            Task.WaitAll(tasks.ToArray());

几点建议:
1) 增加 ServicePointManager.DefaultConnectionLimit 默认为 2 个并发连接

2) 如果所有结果都锁定 table,则线程争用可能很高。如果您没有内存限制,请考虑将结果添加到 ConcurrentDictionary

3) 将请求分成批次以避免耗尽您打开的连接池。

4)小代码注释:
- 如果使用默认设置,请使用 Task.Run 而不是 Task.Factory.StartNew
- i++ 存在竞争条件,可能不准确。您可以使用 Interlocked.Increment 代替