的一般规则是:永远不做阻塞UI线程
在Windows(和Windows CE为好)的UI具有异步特性上。这意味着大多数API调用不一定会立即执行它们应该执行的任何操作。相反,它们生成一系列事件,这些事件放入事件队列中,之后由事件泵检索,实质上,这是一个在UI线程上运行的无限循环,逐个从队列中挑选事件并处理它们。
从上面的结论可以得出结论,如果你在请求某个动作(即在你的情况下显示窗口)之后继续在UI线程上做很长的事情,事件泵将不能继续进行拾取事件(因为你还没有控制它),因此,你的请求的行动无法完成。
一般方法如下:如果您必须执行复杂的数据转换/加载/准备/任何,请在单独的线程上执行它,然后使用Control.BeginInvoke将委托注入UI线程,然后触摸从该委托内部实际的UI控件。
尽管您对多线程带来的“复杂性”非常不理智,但很少有人会害怕。这里有一个小例子来说明这一点:
public void ShowUI()
{
theForm = new MyForm();
theForm.Show();
// BeginInvoke() will take a new thread from the thread pool
// and invoke our delegate on that thread
new Action(PrepareData).BeginInvoke(null,null);
}
public void PrepareData()
{
// Prepare your data, do complex computation, etc.
// Control.BeginInvoke will put our delegate on the UI event queue
// to be retrieved and executed on the UI thread
theForm.BeginInvoke(new Action(PutDataInTheForm));
}
public void PutDataInTheForm()
{
theForm.textBox1.Text = "data is ready!";
}
虽然你可能有其他解决办法玩,一般的想法始终保持不变:如果你做任何事情,在UI线程上长时间,你的用户界面将“冻结”。当你在屏幕上添加新的UI元素时,它甚至不会重绘,因为重画也是一个异步过程。
因此,您必须在单独的线程上完成所有复杂和长期的工作,并且只做简单,小巧,保证在UI线程上运行快速的事情。没有其他选择,真的。
希望这会有所帮助。
as rediculous as this is,Application.DoEvents()静态方法解决了问题,而不必使用任何额外的线程。我知道我不是“做正确的事情“并可能导致UI冻结等,但这对于我们所需要的就足够了。 – 2010-01-20 17:19:04