很多初学者都会碰到这样的问题:循环体内改变窗体Label控件的属性,窗体会假死,值也不会变,直到循环体完了Label才会显示最后的值。设断点会发现其实Label的值已经更改了,只是UI没有重新绘制,还是老样子,如果加上label.Refresh();你会发现其实单线程也可以达到你想要的效果,只不过窗体还是假死状态,因为主线程这会比较忙没有空去重新Paint窗体及其控件。多线程不用多说,Timer是个最简单的例子,Tick事件{//your code} soeasy多线程之所以不用刷新是因为主线程空闲,只要Label值发生变化,就会重新绘制
跨线程访问主窗体控件必须使用委托: int i = 0;
        public void test()
        {
            while (i<100000)
            {
                this.Invoke
                    (
                    (MethodInvoker)delegate()
                    {
                        label1.Text = i.ToString();
                    }
                    );
                i += 100;
            }
        } 
        private void button1_Click(object sender, EventArgs e)
        {
            Thread th = new Thread((ThreadStart)delegate()
            {
                test();
            });
            th.Start();
        }
发这个的目的很简单,有进度条的,或者给用户进度提示的,如果你不想用多线程或者异步操作,值改变一次,你Refresh一次也可以达到效果

解决方案 »

  1.   

    Timer:
    使用 TimerCallback 委托指定希望 Timer 执行的方法。计时器委托在构造计时器时指定,并且不能更改。此方法不在创建计时器的线程上执行,而是在系统提供的 ThreadPool 线程上执行。这不是多线程是什么?
      

  2.   

    哦,你说的是System。Timer,他的确多线程
    UI的不是
      

  3.   

    UI的Timer的确是单线程
    它是按你指定的时间间隔来触发事件的,UI线程用于执行处理
      

  4.   

    跨线程访问窗体控件,用这个Control.CheckForIllegalCrossThreadCalls = false;