我要在一个线程里面对数据进行处理,处理完成后,在主线程进行界面刷新。为了使数据同步我用了AutoResetEvent,如下:
         //成员变量
         AutoResetEvent m_arePda =null;
         
        //加载PDA文件线程
        private void LoadPdaFileThread()
        {
           Thread.Sleep(10000);  //模拟大数据加载 ..
           m_arePda.Set();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            m_arePda = new AutoResetEvent(false);  //创建非终止事件            Thread trd = new Thread(LoadPdaFileThread);
            trd.Start();            m_arePdaList.WaitOne();            //开始将数据在界面显示
            ...
        }问题:现在因为在FormLoad里面用到了m_arePdaList.WaitOne();这样的话,只有当线程执行完,主界面才能显示出来。我想要的是  显示主界面(没数据的)->线程加载数据->主界面显示数据  这样的流程我试过直接在线程里面刷新主界面,不过那个局限性太大,刷一两个控件(如进度条)还没问题,不过同时刷好几个控件的话(如在ListView加数据,又要改变按钮状态,又改变窗口提示文字等)要写很多委托。所以就想先把数据加完,再刷界面。请.NET牛人们不吝赐教。

解决方案 »

  1.   

    softlove03 感谢你的回答    不过 一、我写的是WINDOWS窗口控制(ActiveX)没有Shown事件
             二、我在应用程序中用Shown试过了,效果不是很好。(我在线程加载数据时,会更新界面里的一个ProgressBar,可如果用Show事件后,进度条不到AutoResetEvent.set()后,它不会显示
      

  2.   

    使用线程加载数据到变量里(比如List),然后使用一个Timer定时检测变量里是否有数据,如果有则显示出来,我想你那里主要是加载数据用时比较大。
      

  3.   

    自己可以 写个 显示Show的方法啊!然后在调用,我最近也在 编写 这些问题。关于线程 端口 和 接口 方面的程序 
      

  4.   


    我现在就是在线程里面把数据加载到一个List<string>里面,然后想主线程等子线程把数据加载完成后,把List显示出来,用Timer会不会太浪费了?因为随着线程的执行,我的List里面的数据越来越多,那用Timer定时显示时,肯定要先清空以前显示的,然后把List全部显示出来??这样~~~有点小恐怖。呵呵           对你的回答表示感谢。
      

  5.   

    你不要一个个往List里加嘛,一次性加比如全局List list1 = new List();你不应该用list1.Add();
    应该用list1 = list2;list2是你线程里读取到的数据,这样只有你数据全部读取完全局的List才有数据,Timer才会显示
      

  6.   

    不要用 WaitOne, 等数据加载完之后用 Control.BeginInvoke 或者 Control.Invoke.或者干脆用 BackgroundWorker
      

  7.   

    private void fill_text1()
            {
                for (int i = 0; i < 10000; i++)
                {
                      SetText(i.ToString(), DateTime.Now.ToString("hh:mm:ss ms"));
                      Thread.Sleep(100);
                }
            }
            private void SetText(string text,string datetimes)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new SetTextCallback(SetText), new object[] {text,datetimes  });  //
                }
                else
                {                this.textBox1.Text = text;    //记录当前值
                    this.txt_1_d2.Text = datetimes;   //记录现在时间
                }
            }
            private void fill_text2()
            {
                int i = 0;
                while (i <= 20000)
                {
                     SetText2(i.ToString(), DateTime.Now.ToString("hh:mm:ss ms"));
                     Thread.Sleep(100);
                    i++;
                }
            }
            private void SetText2(string text, string datetimes)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new SetTextCallback(SetText2), new object[] { text, datetimes });  //
                }
                else
                {
                    this.textBox2.Text = text;     //记录当前值
                    this.txt_2_d2.Text = datetimes;   //记录现在时间
                }
    }
      

  8.   

    CGabriel 您好
    不要用 WaitOne, 等数据加载完之后用 Control.BeginInvoke 或者 Control.Invoke. 那我用什么来等待数据加载完呢?
      

  9.   

    fancejackl 您好   看来你误解我的意思了。你举的例子我明白,是用来更新界面了。而且可以把函数放在子线程里面来更新界面。
       不过 一、我要显示的数据,不是显示时间这么简单。我必须要等子线程把数据加载成功后才显示。不然显示的内容肯定是不正确的。我的问题核心是“如何让主界面来等子线程结束,然后自己再把子线程计算的结果显示出来,在此过程中主界面是一直可以看到的。”         二、如果我在子线程中直接刷新界面。那就回到我的题目了:我试过直接在线程里面刷新主界面,不过那个局限性太大,刷一两个控件(如进度条)还没问题,不过同时刷好几个控件的话(如在ListView加数据,又要改变按钮状态,又改变窗口提示文字等)要写很多委托
      

  10.   

    解决办法一: m_arePda = new AutoResetEvent(false) 改为  m_arePda = new AutoResetEvent(true)就不会
    阻塞主线程了
    解决办法二:不用AutoResetEvent感觉有点画蛇添足,你开线程的原因就是要用来不使主界面阻塞
    建议用backgroundworker组件,在dowork方法里取数据(这个方法里不能有对界面操作的代码),在completed事件里更新界面(事件名字可能不对,查查msdn吧)
      

  11.   

    LQknife  您好,谢谢你的回答,刚刚看了一下MSDN,并在我的程序里面试了一下。可行。呵呵。  都是自已常年排斥组件惹的祸啊~~~