我正在用C#编写一个WinForms窗口,它显示大约12个ListBox
和6个ComboBox
控件,每个控件有几百到几千个项目。
填充这些需要一点时间。不久之后 - 只需几秒钟,但用户有一些东西可以看,这样他们就知道程序在等待时会在后台运行。
我有一个通用的“Please Wait”动画无边框最顶层窗口,当这种情况出现时,但是我遇到了动画问题。
对于大多数需要一段时间的任务,我通过以下方式解决这个问题:
Program.ShowPleaseWait(); // Show top-most animation
Thread t = new Thread(stuffToDo); // Run stuffToDo() in separate thread
t.Start();
While (t.IsAlive)
Application.DoEvents(); // Run message queue, necessary for animation
Program.HidePleaseWait(); // Hide top-most animation
并且效果很好。偶尔线程中的东西需要调用一些东西,这有时会导致动画中的小打嗝,但这通常不是什么大问题。
但是,使用此表单,线程中的整个代码是UI代码:填充ListBoxes和ComboBoxes。这意味着一切都必须用Invoke块来包含,这没有任何意义,因为那时首先让它在一个单独的线程中运行是没有意义的。
除了针对这个特定情况删除整个工作线程并在每个循环中每隔约一百次插入Application.DoEvents()
时,我还能做些什么来允许在填充控件时继续工作动画?
答案 0 :(得分:3)
只需在第二个帖子中运行动画即可。您可以拥有多个UI线程,不允许从正在初始化它的线程以外的线程访问任何UI对象。新线程应该接受LoadingAnimationForm
的实例(或任何你称之为动画对话框的实例)并调用Application.Run(animForm);
当主线程完成填充所有内容后,调用animForm.Invoke(animForm.Close)
。不要在主线程上调用animForm
上的任何其他方法。
答案 1 :(得分:1)
一种可能的方法是使用空闲时间处理来执行填充代码。因此,您创建一个对话框类,用于向您显示等待动画。在显示等待对话框的同时挂钩进入空闲时间处理事件。一旦空闲时间处理完全完成,您就会向对话框发送一条消息,告诉它退出。
唯一的复杂因素是你需要组织你的空闲时间事件,因此它每次调用时只执行一些工作,而不是一次性执行所有操作。如果你一次性完成所有操作,那么对话框就没有机会处理并显示更新的等待动画。
答案 2 :(得分:0)