我在获取当前托管在 hubspot 中的所有表单时遇到问题。
我尝试使用一个简单的 for 循环,一次发出一个请求,一次获取一个表单,这种方法有效,但速度非常慢。
然后我认为如果我为每个请求创建一个单独的任务,然后让任务创建每个请求,并将它们存储在一个公共(public)列表中,可能会更好。
问题是我希望列表有 2000 个项目,但我似乎从来没有得到,我得到的项目数量似乎很不一致?
但是怎么会呢?
这就是我设置抓取方案的方式。
private static async Task<IEnumerable<HubspotModel>> GetForms(
string hubspotPath, int pageSize)
{
int totalResults;
int offset = 0;
List<HubspotModel> output = new();
List<Task> tasks = new();
using var client = new HttpClient();
{
System.Net.Http.Headers.HttpResponseHeaders requestHeader = client
.GetAsync($"https://api.hubapi.com{hubspotPath}?" +
$"hapikey={HubspotConfiguration.ApiKey}&limit={1}&offset={0}")
.Result.Headers;
totalResults = int.Parse(requestHeader.GetValues("x-total-count").First());
do
{
tasks.Add(Task.Run(() =>
{
int scopedOffset = offset;
IEnumerable<HubspotModel> forms = GetFormsFromHubspot(hubspotPath,
pageSize, offset, client);
output.AddRange(forms);
}).ContinueWith(requestReponse =>
{
if (requestReponse.IsFaulted)
{
Console.WriteLine("it failed");
}
}));
offset += pageSize;
}
while (totalResults > offset);
await Task.WhenAll(tasks);
}
return output;
}
private static IEnumerable<HubspotModel> GetFormsFromHubspot(string hubspotPath,
int pageSize, int offset, HttpClient client)
{
HttpResponseMessage request = client
.GetAsync($"https://api.hubapi.com{hubspotPath}?" +
$"hapikey={HubspotConfiguration.ApiKey}&limit={pageSize}&offset={offset}")
.Result;
request.EnsureSuccessStatusCode();
string content = request.Content.ReadAsStringAsync().Result;
IEnumerable<Dictionary<string, object>> jsonResponse = JsonSerializer
.Deserialize<IEnumerable<Dictionary<string, object>>>(content,
new JsonSerializerOptions() { });
var guid = Guid.Parse(jsonResponse.First()["guid"].ToString());
var forms = jsonResponse.Select(x => new HubspotModel()
{
id = Guid.Parse(x["guid"].ToString()),
FormName = x["name"].ToString(),
Form = x
});
return forms;
}
最佳答案
首先,我建议将 GetFormsFromHotspot
也设为 async
并使用 await client.GetAsync( ...)
和 await request.Content.ReadAsStringAsync()
分别代替 client.GetAsync(...).Result
和 ReadAsStringAsync().Result
,因为使用 .Result
会阻塞当前线程,因此您将失去异步任务的优势。
但问题的主要原因应该是以下几点
GetFormsFromHubspot(hubspotPath, pageSize, offset, client);
在这里,您使用来自外部作用域的 offset
参数调用 GetFormsFromHubspot
(并且该值不断变化),因此它不会使用您使用时的值创建了那个任务,但是当代码的特定部分真正被执行时,它使用它实际拥有的值。所以用作偏移量的值是非常随机的。您已经尝试创建一个
int scopedOffset = offset;
但你不使用它。而且你在错误的位置创建它。创建 scopedOffset
在任务的外部,但在循环体的内部。因此它将在任务创建时创建。因为它在循环体内,所以将为每个任务创建一个新值。
以下应该可以解决问题(在将 GetFormsFromHubspot
重构为异步之后。
do {
int scopedOffset = offset
tasks.Add(Task.Run(async () => {
IEnumerable<HubspotModel> forms = await GetFormsFromHubspot(hubspotPath, pageSize, scopedOffset, client);
output.AddRange(forms);
})
.ContinueWith(...);
);
offset += pageSize;
} while (totalResults > offset);
关于c# - 尝试从分页网址中获取所有项目时结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72949740/