public delegate void InvokeDelegate(); //创建一个委托
        private void button6_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(InvokeMethod);
            thread.Start();
            thread.Join();           
            listBox2.Items.AddRange(listBox1.Items);   //为什么不执行
            //textBox2.Text = "kjfsdfjk";   //换成这个,就要执行
        }
        public void InvokeMethod()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new InvokeDelegate(AddItem));
            }
        }
        private void AddItem()
        {
            listBox1.Items.Add("万万2邻期和尾");
            listBox1.Items.Add("万万3邻期和尾");
            listBox1.Items.Add("千千2邻期和尾");
            listBox1.Items.Add("千千3邻期和尾");
            listBox1.Items.Add("百百2邻期和尾");
            listBox1.Items.Add("百百3邻期和尾");
        }
在上面的代码中,我用Join方法使主线程阻塞,直到listBox1添加完项之后,才往下执行。可是为什么listBox2没有添加项呢?也就是说listBox2.Items.AddRange(listBox1.Items);这句为什么没有执行呢?
如果是把listBox2.Items.AddRange(listBox1.Items);换成textBox2.Text = "kjfsdfjk";却是执行了的请指教.....

解决方案 »

  1.   

    本帖最后由 bdmh 于 2012-05-31 13:53:19 编辑
      

  2.   


    是C# winform?
    在UI线程之外的线程访问控件解决办法
    C#:
     声明这句  Form.CheckForIllegalCrossThreadCalls = false;   windows phone:把访问页面的代码放在  Dispatcher.BeginInvoke(() => 里面
    例如:
     private void RequestStreamCallBack(IAsyncResult ar)
            {
                Dispatcher.BeginInvoke(() =>
                {
                      //
                 });
            }
      

  3.   

    请把this.BeginInvoke(new InvokeDelegate(AddItem));这句改写成:
    this.Invoke(new InvokeDelegate(AddItem));
    就可以看到正常的效果了。
    当你使用BeginInvoke的话,你的辅助线程将直接结束,你调用thread.Join(); 将变得毫无意义。只有通过Invoke回调的时候,才会等待回调函数执行完毕后才结束线程。
      

  4.   

    listBox1.Items中还没有数据,BeginInvoke是异步执行,thread结束之后AddItem方法还没有执行,
      

  5.   

    可是,把BeginInvoke换成Invoke,还是没有效果,listBox2还是没有添加项
      

  6.   

    可是,把BeginInvoke换成Invoke,还是没有效果,listBox2还是没有添加项
      

  7.   

    有BeginInvoke 没有EndInvoke 是编程的误区,很容易造成未知异常内存泄露。
    两个成对使用,优良的代码是有前必有后,或者直接用Invoke
      

  8.   

    可是,把BeginInvoke换成Invoke,还是没有效果,listBox2还是没有添加项
      

  9.   


    this.Invoke(new InvokeDelegate(AddItem));
    就可以看到正常的效果了。这个是正确的,子线程需要先得到资源才能操作界面上的控件
      

  10.   

    没有添加项才是正确的,有了就对不起Join这个方法的调用了,你先查查Join是干嘛用的再说。整个思路都反了。
      

  11.   

    就算是写成this.Invoke(new InvokeDelegate(AddItem));还是没有效果啊?listBox2还是没有添加项
      

  12.   

      public delegate void InvokeDelegate(); //创建一个委托
            private void button6_Click(object sender, EventArgs e)
            {
                Thread thread = new Thread(InvokeMethod);
                thread.Start();
            }
            public void InvokeMethod()
            {
                if (this.InvokeRequired)
                {
                    this.BeginInvoke((MethodInvoker)AddItem);
                }
            }
            private void AddItem()
            {
                listBox1.Items.Add("万万2邻期和尾");
                listBox1.Items.Add("万万3邻期和尾");
                listBox1.Items.Add("千千2邻期和尾");
                listBox1.Items.Add("千千3邻期和尾");
                listBox1.Items.Add("百百2邻期和尾");
                listBox1.Items.Add("百百3邻期和尾");            for (int i = 0; i < listBox1.Items.Count; i++)
                {                listBox2.Items.Add(listBox1.Items[i]);
                }
            }
      

  13.   

    private void AddItem()
    {
    listBox1.BeginUpdate();
    ...
    listBox1.EndUpdate();
    }
      

  14.   

      public delegate void InvokeDelegate(); //创建一个委托
            private void button6_Click(object sender, EventArgs e)
            {
                Thread thread = new Thread(InvokeMethod);
                thread.Start();
            }
            public void InvokeMethod()
            {
                if (this.InvokeRequired)
                {
                    this.BeginInvoke((MethodInvoker)AddItem);
                }
            }
            private void AddItem()
            {
                listBox1.Items.Add("万万2邻期和尾");
                listBox1.Items.Add("万万3邻期和尾");
                listBox1.Items.Add("千千2邻期和尾");
                listBox1.Items.Add("千千3邻期和尾");
                listBox1.Items.Add("百百2邻期和尾");
                listBox1.Items.Add("百百3邻期和尾");
                listBox2.Items.AddRange(listBox1.Items);        }
      

  15.   

    不管用Invoke还是BeginInvoke都不会先填充listBox1,再填充listBox2,因为button6_Click 和 this.Invoke/BeginInvoke都是UI线程去做的事情,只要button6_Click 还没有执行完,Invoke都不会执行。所以button6_Click里面的事情必须先处理完,也就是说,listBox2.Items.AddRange(listBox1.Items)先执行,而这时候listBox1.Items还没有东西。要想listBox1加载完后listBox2复制过来,AddItem()里面都写上是一种方法,或者是Invoke完了之后回调一个方法。
      

  16.   

    原来你问的不是执行顺序问题,而是执行效果。那么你的写法本身有误,因为你需要在listBox1添加后去执行添加,但是你Join()方法却不能保证多线程的结束,listBox1一定执行了添加过程,如果用Invoke的话,调用Join又会出现资源死锁问题。因此必须通过回调函数来操作。
    public delegate void InvokeDelegate(); //创建一个委托
      private void button6_Click(object sender, EventArgs e)
      {
         AsyncCallback callback = new AsyncCallback((t) =>
         {
             this.Invoke(new Action<ListBox.ObjectCollection>(listBox2.Items.AddRange), listBox1.Items);
          });
         //开启多线程执行InvokeMethod方法,执行完毕后自动回调callback方法,完成listBox2内部项的添加。
         new Action(InvokeMethod).BeginInvoke(callback ,null);
      }
      public void InvokeMethod()
      {
      if (this.InvokeRequired)
      {
      this.Invoke(new InvokeDelegate(AddItem));
      }
      }
      private void AddItem()
      {
      listBox1.Items.Add("万万2邻期和尾");
      listBox1.Items.Add("万万3邻期和尾");
      listBox1.Items.Add("千千2邻期和尾");
      listBox1.Items.Add("千千3邻期和尾");
      listBox1.Items.Add("百百2邻期和尾");
      listBox1.Items.Add("百百3邻期和尾");
      }
      

  17.   

    无论在button6_Click中的何处位置,都要等到button6_Click 执行完,才执行BeginInvoke或是Invoke吗?怎么会是这样的啊,不是很乱吗?