【问题标题】:Why is the GUI frozen while foreaching through a ListView and using GetStringAsync?为什么在通过 ListView 搜索并使用 GetStringAsync 时 GUI 会冻结?
【发布时间】:2015-11-11 22:45:30
【问题描述】:

我正在使用 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 放在另一个线程中的信息,但几天以来我一直在为性能优化而苦苦挣扎。首先,我不太明白为什么在执行 foreach 时 GUI 会冻结。鉴于异步 HTTP 请求不在主线程上完成工作(至少我希望这是异步的代表),它不应该冻结请求。此外,编辑 SubItems 的操作应该很快,特别是因为 List 中只有大约 10 个项目。

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

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

【问题讨论】:

  • 您在异步方法上调用 .Result,这意味着它将阻塞。由于这发生在 UI 中,这就是它冻结的原因 - 你并没有真正进行异步调用。我建议使用后台工作线程,或者在 UI 中重做您的方法以真正利用 async/await。也许是您调用(和等待)的第二种方法,它执行 foreach 并进行网络调用。
  • 在异步方法上调用 .Result 是邪恶的...... :)
  • 我花了这么长时间,但最后程序运行没有冻结。只因为一个字。非常感谢大家!

标签: c# json multithreading listview httprequest


【解决方案1】:

当您执行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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    • 2022-01-16
    • 2021-04-25
    • 1970-01-01
    相关资源
    最近更新 更多