从后台线程

时间:2018-02-24 07:37:46

标签: c# datagridview

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

我想证实我的结论。

在填充的信息源非常快的情况下(即它不需要花费很多处理时间来获取信息本身),在我看来,花费时间的处理实际上是将它提供给DataGridView 。但是,这必须在UI线程上完成,就像控件所在的那样。

如果是这样的话,那么在后台尝试做任何事情的好处似乎有限,并且推论是没有有效的方法来填充DataGridView而没有更新UI线程。是吗?

当然,必须以某种方式完全异步填充DataGridView,同时用户仍然可以与UI进行交互?

1 个答案:

答案 0 :(得分:0)

  

当然,必须以某种方式完全异步填充DataGridView,同时用户仍可以与UI进行交互?

有很多方法可以做。

通过Async / await进行寻呼内联常规代码

如果您正在从中获取数据(无论是直接数据库连接; 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。