簡體   English   中英

C# 在 foreach 循環中進行異步 http 請求

[英]C# Make async http requests within a foreach loop

我需要發出多個 Web 請求,其中 URI 位於 DataTable 中。 早些時候我有下面的代碼。 但我意識到這會進行同步調用,因為await會等到 GET/POST 調用完成並處理響應,然后繼續進行下一次迭代。

foreach (DataRow dr in dt.Rows)
{
    activeTasks.Add(SendRequestAsync(dr));
    Task.WhenAll(activeTasks).Wait();
}

private async Task<string> SendRequestAsync(DataRow dr)
{
    using (var client = new HttpClient())
    {
        string reqMethod = (dr["RequestMethod"] != null && dr["RequestMethod"].ToString() != "") ? dr["RequestMethod"].ToString() : "GET";
        client.BaseAddress = new Uri(dr["URL"].ToString());
        client.DefaultRequestHeaders.Accept.Clear();
        string reqContentType = (dr["RequestContentType"] != null && dr["RequestContentType"].ToString() != "") ? dr["RequestContentType"].ToString() : "text/xml";
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(reqContentType));

        HttpResponseMessage response = null;
        try
        {
            if (reqMethod == "GET")
                response = await client.GetAsync(client.BaseAddress.AbsoluteUri);
            else
                response = await client.PostAsync(client.BaseAddress.AbsoluteUri, null);

            response.EnsureSuccessStatusCode();
            var responseText = await response.Content.ReadAsStringAsync();
            return responseText;
        }
        catch (Exception e)
        {
            return "-1";
        }
    }
}

然后我遇到了Parallel功能並改用Parallel.ForEach 像這樣:

Parallel.ForEach(rows, dr =>
{
    activeTasks.Add(SendRequestAsync(dr));
    Task.WhenAll(activeTasks).Wait();
});

這工作正常,實現了並行性,請求是異步的,與早期的解決方案相比,它在很短的時間內完成。 但問題是它不可靠 - 有時我會遇到類似的錯誤

  • System.IndexOutOfRangeException:索引超出了數組的范圍
  • System.InvalidOperationException:集合已修改; 枚舉操作可能無法執行。

無論如何,我們可以在 foreach 中實現 http 異步調用嗎?

正如@Johnathon_Chase 所說,只需將您的WhenAll()調用移出循環:

foreach (DataRow dr in dt.Rows)
{
    activeTasks.Add(SendRequestAsync(dr));
}
Task.WhenAll(activeTasks).Wait();

for循環填充集合,然后Task.WhenAll()在請求完成時阻塞。

Parallel.ForEach用於 CPU 密集型操作,不是為 I/O 密集型操作或異步設計的。

您可以在foreach循環中await就好了。 但是,包含循環的方法本身必須是異步的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM