【发布时间】:2021-12-08 21:43:34
【问题描述】:
我需要每秒处理来自总共 80 个不同 ID 的 4000 个消息包。我有一个DataGrid。我有ObservableCollection 绑定到DataGrid。我尝试了 2 种方法来刷新 UI 而不会冻结。我都没有成功。
1.方式
如果有来自不同 ID 的消息,我会将其添加到我的收藏中。如果它来自同一个ID,我删除旧的并获取新的。
if (MessagePacket._jobs.Where(X => X.ID == dataPacket.ID).FirstOrDefault() == null)
{
MessagePacket._jobs.Add(dataPacket);
}
else
{
for (int x = 0; x < MessagePacket._jobs.Count; x++)
{
if (MessagePacket._jobs[x].ID == dataPacket.ID)
{
MessagePacket._jobs.RemoveAt(x);
MessagePacket._jobs.Add(dataPacket);
}
}
}
2.Way
我正在修改数据而不删除它并刷新集合。
注意:我尝试每 50 毫秒刷新一次集合,而不是在每次打包后刷新一次。还是很慢。
if (MessagePacket._jobs.Where(X => X.ID == dataPacket.ID).FirstOrDefault() == null)
{
MessagePacket._jobs.Add(dataPacket);
}
else
{
for (int x = 0; x < MessagePacket._jobs.Count; x++)
{
if (MessagePacket._jobs[x].ID == dataPacket.ID)
{
MessagePacket._jobs[x].DLC = dataPacket.DLC;
MessagePacket._jobs[x].RTR = dataPacket.RTR;
MessagePacket._jobs[x].IDE = dataPacket.IDE;
MessagePacket._jobs[x].Byte0 = dataPacket.Byte0;
MessagePacket._jobs[x].Byte1 = dataPacket.Byte1;
MessagePacket._jobs[x].Byte2 = dataPacket.Byte2;
MessagePacket._jobs[x].Byte3 = dataPacket.Byte3;
MessagePacket._jobs[x].Byte4 = dataPacket.Byte4;
MessagePacket._jobs[x].Byte5 = dataPacket.Byte5;
MessagePacket._jobs[x].Byte6 = dataPacket.Byte6;
MessagePacket._jobs[x].Byte7 = dataPacket.Byte7;
MessagePacket._jobs[x].Time = DateTime.Now.ToString("HH:mm:ss");
CollectionViewSource.GetDefaultView(MessagePacket._jobs).Refresh();
}
}
}
如何在不冻结用户界面的情况下加快进程。或者你能展示另一种方式吗?从现在开始谢谢你。
【问题讨论】:
-
这是 WPF、UWP 还是 Windows.Forms,因为答案可能不同?
-
50 毫秒的刷新率对最终用户是否有价值?你可以把它限制在视觉上更容易消化的东西。
-
冻结是什么意思?完全无响应,或在响应/无响应状态之间切换?那么意识到当你真正刷新数据时,ui线程将在整个过程中被阻塞?所以例如。如果你的进程需要 10 毫秒并且你每 50 毫秒执行一次,它会每 50 毫秒冻结 10 毫秒。
-
请注意,您可以将
MessagePacket._jobs.Where(X => X.ID == dataPacket.ID).FirstOrDefault() == null简化为MessagePacket._jobs.FirstOrDefault(X => X.ID == dataPacket.ID) == null,然后进一步简化为!MessagePacket._jobs.Any(X => X.ID == dataPacket.ID)或MessagePacket._jobs.All(X => X.ID != dataPacket.ID)。如果您使用 VS 进行开发,“Roslynator”插件将为您提供有关这些简化的提示。 -
试试
MessagePacket._jobs[x] = dataPacket;而不是复制所有数据。您不需要实现 INotifypropertyChanged ro call Refresh()。
标签: c# wpf datagrid observablecollection