Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在后台更新列表时UI线程挂起?_C#_Wpf_Multithreading - Fatal编程技术网

C# 为什么在后台更新列表时UI线程挂起?

C# 为什么在后台更新列表时UI线程挂起?,c#,wpf,multithreading,C#,Wpf,Multithreading,我认为我在线程方面有很好的处理能力,直到我遇到一个场景,在这个场景中我想对不同网格的更新进行基准测试 我创建了一个带有网格控件的窗口,绑定了一个observateCollection,并用5000行复杂数据类型(不包含锁)填充它 然后,我使用 Task.Factory.StartNew() 这经历了一个非常紧密的循环(1000万次迭代),更新了myObservableCollection中随机项上的随机属性,当然每个属性都会引发一个INotifyPropertyChanged事件 现在,由于

我认为我在线程方面有很好的处理能力,直到我遇到一个场景,在这个场景中我想对不同网格的更新进行基准测试

我创建了一个带有网格控件的窗口,绑定了一个
observateCollection
,并用5000行复杂数据类型(不包含锁)填充它

然后,我使用

 Task.Factory.StartNew()
这经历了一个非常紧密的循环(1000万次迭代),更新了my
ObservableCollection
中随机项上的随机属性,当然每个属性都会引发一个
INotifyPropertyChanged
事件

现在,由于更新都发生在后台线程上,我希望UI能够更新,尽管很难跟上后台线程在一个紧密的循环中旋转

相反,UI冻结了几秒钟(但没有变为空白或产生通常旋转的厄运光标),然后在后台线程完成后返回

我的理解是,后台线程在生成成吨的INPC时会对内核造成相当大的负担,每个INPC都会由WPF运行时自动编组到UI线程

现在UI线程什么也没做,所以我希望它会使用所有这些INPC并更新网格,但它没有;没有发生任何更新。然而,当我使用计时器(而不是紧循环)来完成这项工作时,它工作得很好


有人能告诉我UI线程到底在做什么吗?提前谢谢

如果您用大量这样的已调度更新阻塞了消息泵,其他消息将没有机会被处理,这将导致您观察到的“冻结”效果

这里有一件事可以帮助您在UI控件上使用数据虚拟化,以便只有可见的行被实际绑定并侦听INPC更新。默认情况下,这是为启用的,但如果您使用更自定义的方法来可视化数据,则可能会出现问题

这就是说,这对频繁修改当前可见的项目没有帮助,因为真正的快速更新仍然会阻塞调度程序。如果您有这样一个用例,您可能希望稍微隔离视图模型对象,并有一种方法“批量”更新。一种技术是在执行一系列更新时有一种抑制通知的方法,然后在每个实例上调用
RaisePropertyChanged(null)
(或INPC helper基类上的任何等效方法),以更新到该实例的所有绑定


另一种机制是在其他层(视图模型实例所表示的任何模型对象)中进行数据更新,然后以定义良好的间隔将这些属性复制到视图模型类。为了快速更新背景数据,我经常使用轮询循环,而不是在事件上触发,这仅仅是因为事件发生的频率比用户界面所关心的要高,并且会降低后台处理速度,从而不断发送所有这些不必要的通知。

您能提供最短的代码示例来说明这个问题吗?您所说的“紧循环”是指每次迭代都没有延迟吗?这看起来像是一个简单的例子,用户界面被无法跟上的更新轰炸;您(或知情人士)能否详细说明消息泵在此期间正在做什么?为什么调度员会“阻塞”?例如,假设我是UI线程,你是工人,你生成更新的速度比我处理更新的速度快。我们仍然作为完全独立的线程并行工作,所以对于每100个更新,我应该能够处理其中的10个,不是吗?我当然会落后,但我应该仍然在做工作,而不是显得无所事事。@Anthony,这有点复杂,但我的理解是,数据绑定有一个相对较高的优先级,这意味着发送的通知队列会堆积起来,并在大量其他希望处理的消息之前得到服务。因此,应用程序并不是真的死锁,但也可能是因为它实际提供的响应有限。特别是,“输入”和“呈现”消息的优先级都低于“数据绑定”,这意味着应用程序对输入没有响应,并且不更新其呈现的输出,但实际的Windows处理程序仍在处理中(并排队),因此窗口仍会显示,只显示最后一次缓存的渲染输出;我完全忘记了数据绑定的优先级。。。你会不会碰巧有一篇详细描述这一点的文章的链接?更新:没关系,我有一秒钟的精神障碍。我现在都明白了,非常有道理,谢谢!