应用程序在添加数千行时无响应

时间:2011-03-12 22:49:44

标签: .net winforms multithreading datagridview

我有一个Windows窗体应用程序,它创建一个后台线程来搜索文件并将匹配的文件名添加到DataGridView。后台线程使用BeginInvoke向DataGridView添加行,如果后台线程没有返回数千个结果,一切正常。即使后台线程处理数千个文件,UI也能正常工作,除非它尝试向DataGridView输入几千行。

我尝试逐个添加行,并缓冲它们并一次添加100行。但是应用程序UI始终没有响应。后台进程比UI线程工作得更快,并且总有新行要添加到DataGridView。

我甚至尝试过Application.DoEvents(在UI线程中),但它也没有帮助。

有什么想法吗?我可以在不向后台线程添加延迟的情况下修复它吗?

提前致谢

5 个答案:

答案 0 :(得分:2)

确保分别在添加所有新行之前和之后调用SuspendLayout()ResumeLayout()。在添加所有行之前不调用SuspendLayoutDataGridView将在每个添加的行之后重新绘制自己,这会使事情变慢一些。

答案 1 :(得分:2)

看起来使用Invoke而不是BeginInvoke来添加行是最简单的解决方案。它稍微减慢了后台线程,但它阻止了UI无响应。 由于您没有向后台线程添加预定义的延迟,我认为将后台线程减慢一点只是为了让UI线程赶上来是可以接受的。 使用SuspendLayout和ResumeLayout在使用BeginInvoke时也没有帮助。 我没有尝试使用共享行的虚拟模式,但这也可能有所帮助。

答案 2 :(得分:1)

答案 3 :(得分:0)

一种方法是让主线程创建一个BlockingCollection<string>,作为后台线程可以添加字符串的队列。后台线程完成添加后,会调用CompleteAdding

UI线程还会创建一个以某种频率触发的计时器(可能是您通过实验确定的)。计时器的Elapsed事件会查看队列中是否有任何内容,如果有,则删除一个项目并将其添加到DataGridView。当计时器的Elapsed事件看到队列的IsComplete属性为True时,它会停止并处理计时器。

提供你的计时器不会做得太快,这应该保持你的UI响应,你不必摆弄后台线程的延迟。

答案 4 :(得分:0)

我遇到的问题似乎是每次添加一行时滚动条会重新绘制自己,如果我添加let就像10000行一样。我通过在填充之前将datagridview的滚动条设置为None来解决此问题,并在填充后进行恢复,如下所示:

ScrollBars bars = this.ScrollBars; this.ScrollBars = System.Windows.Forms.ScrollBars.None;

...在这里填充(我有一个覆盖的DataGridView控件)

this.ScrollBars = bars;

在添加数千行的情况下,SuspendLayout因某些原因无效。