为什么在通过 ListView 进行 foreaching 和使用 GetStringAsync 时 GUI 被冻结?

Why is the GUI frozen while foreaching through a ListView and using GetStringAsync?

我正在使用 foreach 遍历 ListView,其项目是从 XML 文件加载的。然后我在我的网页上执行一个带有项目名称的异步 HTTPRequest 以获取 JSON 字符串,到目前为止它运行良好。

 HttpClient client = new HttpClient();

 foreach (ListViewItem item in lV_Items.Items)
  {
   JObject o = JObject.Parse(client.GetStringAsync("http://000.000.000/?item=" + HttpUtility.UrlEncode(item.Text)).Result);
  }

然后我将 JSON 中的新值编辑到项目 SubItem

string amount= (string)o["amount"];
item.SubItems[1].Text = amount;

我运行在每分钟重复一次的计时器中使用此代码。但是,几天以来我一直在努力进行性能优化,尽管我阅读了很多关于例如 ListView.BeginUpdate 或将 HTTPRequest 放在另一个线程中的内容。首先,我不太明白为什么 GUI 在执行 foreach 时会冻结。考虑到不在主线程上工作的异步 HTTP 请求(至少我希望这是异步所代表的),它不应该在请求时冻结。另外编辑SubItems的操作应该是相当快的,特别是因为List中只有大约10个项目。

我考虑过将 Items 加载到 List(动态集合)中,而不是直接加载到 ListView 中。然后我将运行 1个计时器定期将列表发送到另一个线程,然后线程刷新列表中的值并将其发送回主窗体。在 Mainform 中有第二个计时器,它定期将 List 放入 ListView(仅用于可视化)。两个计时器,因为我认为如果将以上两者都放入一个计时器中,计时器将等待线程完成,导致应用程序仍然冻结。

我想这是一个想法,但是有很多不透明的工作已经完成,维护/调试可能会更难。任何关于我应该如何做以及更好的想法将不胜感激。

当您执行 client.GetStringAsync(...).Result 时,您会阻塞直到 GetStringAsync 完成,这违背了使用异步方法的目的。您应该改用 await

string json = await client.GetStringAsync("http://000.000.000/?item=" + HttpUtility.UrlEncode(item.Text));
JObject o = JObject.Parse(json);

(注意你需要制作你的方法async)