【发布时间】:2012-10-18 09:17:11
【问题描述】:
我正在使用 .Net 4.0 和 VS2010。
我的程序只是一个多线程获取请求发送器,它更新一个 bindingList 并通过 DataGridView 显示列表。 datagridview 处于虚拟模式。此外,我制作了一个文本框和状态栏来显示请求的状态,一个请求通常会在文本框中添加 4-5 行并更改状态栏中的数字。
工作负载保持不变,每两秒一个请求。请求速度很快,大部分时间只有一个请求突出。新请求线程由最后一个旧请求线程调用。 UI 使用 begininvoke 和 delegate 每个线程更新几次。
MyInvoke mi = new MyInvoke(change);
this.BeginInvoke(mi, new Object[] { true, "Row " + pos + " standing by...", (pos + 1),0 });
我一开始在 datagridview 上显示全部 3000 个请求,内存使用量为 30MB。当内存使用量为 4XMB 达到 2XXX 请求时,我可以看到状态栏编号和文本框更新速度越来越慢。例如,2000->2001->2002->2003 变为 2000->2003。
如果我选择应用程序窗口,有时整个 UI 甚至会冻结。我的 datagridview 用虚拟模式固定在几行上。我相信这是UI线程的问题。当它冻结时,我可以等到所有请求都完成并且一切再次变得顺利。
对正在发生的事情有什么想法吗?
【问题讨论】:
-
可能是begininvoke过度使用的原因,我试试看。但是谁能解释为什么这只会在 2XXX 行之后发生?大多数时候消息的数量是相同的。一个愚蠢的问题,是否可以使窗口窗体对象位于不同的线程中,这样整个窗体就不会冻结?
-
不,不要将 windows 窗体对象放在不同的线程中,这是问题的一部分。 GUI 不是线程安全的。根据上面 MVP Peter Richie 所写的链接,将更新 GUI 的调用保留在主线程中:
Windows controls must be accessed on the thread where their message pump is running. -
找出问题所在。不知何故与过度使用 begininvoke 有关。我将 textbox1.Text += "string" 更改为 textbox1.AppendText("string") ,现在它真的很流畅。更新整个文本框的工作量太大,导致其他begininvoke无法完成工作。