在我的WPF C#应用程序中,我有一个小圆圈动画,我在处理过程中显示,让用户知道应用程序正在“思考”,他们应该放松一下。这是一个单独的exe。因此,例如,当用户单击按钮运行分析时(可能需要5-10秒),我开始显示动画的过程,当它全部完成时,我停止该过程。在此期间,新生成的子线程用于处理后台任务。完成后,UI会更新,由于数据网格复杂,可能需要几秒钟。
虽然这在技术上有效,但我宁愿以不同的方式处理它。我宁愿在线程工作时让应用程序自动检测并自动显示动画,当线程全部完成时,它会停止显示它。我可以轻松地检测后台线程,但是如何检测UI线程?我宁愿这样做,因为有几次我不小心错过了杀死应用程序,并且在处理完成后它仍在运行。这可以防止这种情况。
UI线程启动和停止时是否会触发事件?如果没有,让我说我在那里扔了一个计时器,每1/2秒就会被触发一次,是否有一个我可以做的调用会告诉我UI线程的状态?
由于
答案 0 :(得分:2)
这是一个捕获22。如果您有一些代码可以运行以确定UI线程被阻止,那么您将无法启动动画,因为UI线程被阻止;直到UI线程完成它正在处理的任务之后才会显示动画,此时动画不再相关。
在几乎所有情况下,您应该将长时间运行的任务移动到另一个后台线程,而不是在UI线程中执行它们。您可以在此类任务开始时显式禁用表单上的部分/全部控件,并在结束时启用它们。我会高度阻止你阻止UI线程作为禁用表单的一种方法,因为从用户的角度来看,它看起来好像程序由于编程错误而无法工作,相反认为这是理想的行为。
答案 1 :(得分:2)
更好的方法是移动处理UI(例如使用BackgroundWorker
并让后台工作人员向UI线程发布通知(已启动,进度更新,已完成)。
不要重新发明轮子并将处理逻辑移出UI线程。
答案 2 :(得分:1)
您可以通过应用程序的Dispatcher
尝试将任务添加到具有非常低优先级的主UI线程中:
Application.Current.Dispatcher.BeginInvoke((ThreadStart)StopAnimation, DispatcherPriority.ApplicationIdle);
...
private void StopAnimation()
{
...
}
这基本上说“当主UI线程绝对没有更好的事情要做时,请调用StopAnimation()”。诀窍是找到正确的时间来调用.BeginInvoke
- 在网格加载之前或期间。