这个问题已经被问了很多,我已经阅读了Stackoverflow上的所有帖子。
我想证实我的结论。
在填充的信息源非常快的情况下(即它不需要花费很多处理时间来获取信息本身),在我看来,花费时间的处理实际上是将它提供给DataGridView 。但是,这必须在UI线程上完成,就像控件所在的那样。
如果是这样的话,那么在后台尝试做任何事情的好处似乎有限,并且推论是没有有效的方法来填充DataGridView而没有更新UI线程。是吗?
当然,必须以某种方式完全异步填充DataGridView,同时用户仍然可以与UI进行交互?
答案 0 :(得分:0)
当然,必须以某种方式完全异步填充DataGridView,同时用户仍可以与UI进行交互?
有很多方法可以做。
如果您正在从中获取数据(无论是直接数据库连接; REST还是WCF调用)支持分页,那么您可以通过内联async/await
获取数据页面并为每个项目添加行在页面中返回。
e.g。
// somewhere in your UI code
async Task LoadAsync(List<Page> pages)
{
foreach (var page in pages)
{
var stuff = await service.GetMovieSalesPagedAsync (page);
foreach (var item in stuff)
{
_dataGrid.Rows.Add (/* convert item then add it here */);
}
}
}
这比一次性请求所有数据然后尝试为每个项目添加行更快。后者只会阻止用户界面。
上述方法的好处是代码内联且易于阅读。
当需要显示大量数据并且您希望在UI方面获得最佳性能时,此技术会更好。如果源不支持分页,它也很有用。
在这里你可以产生一个Task
,其作用是一次检索一个页面(或一次全部),然后将每个页面结果添加到ConcurrentQueue<>
以获得UI线程。如果必须检索所有内容,请手动将结果分解为页面。
同时,在Application.Idle
处理程序中尝试从队列中弹出一个项目,如果找到一个项目,则将新项目作为行添加到数据网格中。现在,根据您的应用程序,您可以选择处理所有可用页面或等待下一个应用程序空闲事件。这可能需要一些微调。等待下一个应用程序空闲使您的应用程序可以很好地处理UI响应。
这将导致数据网格逐步填充而不是一次性填充。
这种方法的一个缺点是代码不再是内联的。你有一个代码块负责获取和存储数据;另一个用于将其泵入UI。