C# 从后台线程填充DataGridView

C# 从后台线程填充DataGridView,c#,datagridview,C#,Datagridview,这个问题被问了很多,我已经阅读了所有关于Stackoverflow的帖子 不过我想确认我的结论 在填充的信息源相当快的地方(即获取信息本身不需要太多处理时间),在我看来,花费时间的处理实际上是将信息输入到DataGridView中。但是,这必须在UI线程上完成,因为控件就在那里 如果是这样的话,那么尝试在后台做任何事情的好处似乎都是有限的,由此产生的结果是,没有有效的方法来填充DataGridView而不阻塞UI线程。是这样吗 当然,一定有一种方法可以完全异步地填充DataGridView,而用

这个问题被问了很多,我已经阅读了所有关于Stackoverflow的帖子

不过我想确认我的结论

在填充的信息源相当快的地方(即获取信息本身不需要太多处理时间),在我看来,花费时间的处理实际上是将信息输入到DataGridView中。但是,这必须在UI线程上完成,因为控件就在那里

如果是这样的话,那么尝试在后台做任何事情的好处似乎都是有限的,由此产生的结果是,没有有效的方法来填充DataGridView而不阻塞UI线程。是这样吗

当然,一定有一种方法可以完全异步地填充DataGridView,而用户仍然可以与UI交互

当然,一定有一种方法可以完全异步地填充DataGridView,而用户仍然可以与UI交互

有很多方法可以做到这一点

通过使用常规代码内联的Async/await进行分页 如果从中获取数据的内容(无论是直接数据库连接;REST还是WCF调用)支持分页,则可以通过内联
async/await
获取数据页,并为页面中返回的每个项目添加行

e、 g

//用户界面代码中的某个地方
异步任务加载异步(列表页)
{
foreach(页面中的变量页面)
{
var stuff=await service.GetMovieSalesPagedAsync(第页);
foreach(stuff中的var项)
{
_dataGrid.Rows.Add(/*转换项,然后将其添加到此处*/);
}        
}
}
这比一次性请求所有数据然后尝试为每个项目添加行要快。后者只会阻塞UI

上述方法的好处是代码是内联的,更易于阅读

应用程序空闲期间具有渐进填充的专用任务 当需要显示大量数据并且希望在UI方面获得最佳性能时,此技术更适合。如果源不支持分页,它也很有用

在这里,您可以生成一个
任务
,其任务是一次一页(或一次全部)检索数据,然后将每个页面结果添加到一个
ConcurrentQueue
,以利于UI线程。如果必须检索所有结果,请手动将结果分成多个页面

同时,在您的
应用程序.Idle
处理程序中,尝试从队列中弹出一个项目,如果找到一个,则将新项目作为行添加到数据网格中。现在,根据您的应用程序,您可以选择处理所有可用页面或等待下一个应用程序空闲事件。这可能需要一些微调。等待下一个应用程序空闲可以让你的应用程序发挥良好的UI响应能力

这将导致逐步填充数据网格,而不是一次填充所有数据网格


这种方法的缺点是代码不再是内联的。您有一块代码负责获取和存储数据;另一种方法是将其泵入UI

用户一次可以看到多少数据。您试图将多少数据放入视图中。你的瓶颈在哪里?添加您的技术标签-winfowms?错。更新DGV的时间就是刷新DGV的时间。因此,通常只有在最后进行刷新才能加快代码的速度。最好的方法是使DGV的数据源成为数据表,然后在后台模式下更新数据表。然后在最后将更新后的数据表设置到DatSource。我只添加了几百行,但其中一些有大量的文本。我还尝试在更新期间禁用DataGridView,并暂停布局,但性能仍然不是最优的。看起来数据表路由值得一试,所以我来看看。这里似乎有一个很好的例子:谢谢你的帮助。我仍然有这个问题。我正在后台线程中填充一个数据表,这几乎是即时的。然后,我将该DataTable分配给DataGridView所指向的BindingSource。我必须在UI线程上将DataTable分配给BindingSource,否则会出现跨线程异常。但是,执行单行“sql\u query\u results.DataSource=query\u results;”大约需要5-10秒,这比我在UI线程上完成全部任务并直接填充DataGridView时要慢。不知道这里发生了什么。
// 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  */);  
        }        
    }
}