为什么 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
代替
我们有一个数据 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
代替