none
控件Invoke方法的疑问 RRS feed

  • 问题

  • 以下是为了在UI线程中显示数据; 是有另一个线程使用这个函数; 为了解决在一个线程中访问另一个线程控件的问题.

    我现在的疑问是, AddMessageDelegate d = AddMessage; 这貌似是委托指向了自身.

    这一句; 为何不如注释中我所写句子那样用呢

    完整程序如下:

    ----------------------------------------------------------------------------------

    using System.Threading;
    namespace ThreadExample
    {
        class Class1
        {
            public volatile bool shouldStop;
            private Form1 form1;
            public Class1(Form1 form1)
            {
                this.form1 = form1;
            }

            public void Method1(object obj)
            {
                string s = obj as string;
                form1.AddMessage(s);
                form1.AddMessage("a");
               // while (shouldStop == false)
               // {
               //     Thread.Sleep(100);   //线程1休眠100毫秒
               //     form1.AddMessage("a");
               // }
                
                form1.AddMessage("\n线程Method1已终止");
            }

            public void Method2()
            {
                form1.AddMessage("b");
               // while (shouldStop == false)
                //{
               //     Thread.Sleep(100);   //线程2休眠100毫秒
                //    form1.AddMessage("b");
                //}
                form1.AddMessage("\n线程Method2已终止");
            }
        }
    }
    ----------------------------------------------------------------------------------------------

    namespace ThreadExample
    {
        public partial class Form1 : Form
        {
            Thread thread1, thread2;
            Class1 class1;

            public Form1()
            {
                InitializeComponent();
                class1 = new Class1(this);
                buttonStart.Click += new EventHandler(buttonStart_Click);
                buttonStop.Click += new EventHandler(buttonStop_Click);
            }

            private void buttonStart_Click(object sender, EventArgs e)
            {
                richTextBox1.Clear();
                class1.shouldStop = false;
                thread1 = new Thread(class1.Method1);
                thread1.IsBackground = true;
                thread2 = new Thread(class1.Method2);
                thread2.IsBackground = true;
                thread1.Start("a method start\n");
                thread2.Start();

               // Thread t = new Thread(new ThreadStart(SetLbText));
                Thread t = new Thread(SetLbText);
                t.Start();

            }

            private void buttonStop_Click(object sender, EventArgs e)
            {
                class1.shouldStop = true;
                thread1.Join(0);
                thread2.Join(0);
            }

            private delegate void AddMessageDelegate(string message);
            public void AddMessage(string message)
            {
                if (richTextBox1.InvokeRequired)
                {
                   AddMessageDelegate d = AddMessage;
                   richTextBox1.Invoke(d, message);
                   //AddMessageDelegate d = (string isr) => { richTextBox1.Text = isr; };
                   //richTextBox1.Invoke(d, "test");  我试图修改之处
                }
                else
                {
                    richTextBox1.AppendText(message);
                }
            }
        }
    }

    2012年9月21日 20:38

答案

  • 你好,

    按照你没有注释的语句,有问题吗?我测试过完全可以啊(简化了测试代码):

    public partial class Form1 : Form
        {
            private delegate void AddMessageDelegate(string message);
    
            public void AddMessage(string message)
            {
                if (richTextBox1.InvokeRequired)
                {
                    AddMessageDelegate d = AddMessage;
                    richTextBox1.Invoke(d, message);
                }
                else
                {
                    richTextBox1.AppendText(message);
                }
            }
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
              
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(() => { AddMessage("aaa"); });
                th.IsBackground = true;
                th.Start();
            }
    
           
        }
    不过有一个问题需要注意——第一次(即Thread.Start之后调用那个AddMessage),此时InvokeRequired=true,此时使用Control.Invoke(……),那么方才InvokeRequired=false

    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年9月22日 3:28
    版主

全部回复

  • 你好,

    按照你没有注释的语句,有问题吗?我测试过完全可以啊(简化了测试代码):

    public partial class Form1 : Form
        {
            private delegate void AddMessageDelegate(string message);
    
            public void AddMessage(string message)
            {
                if (richTextBox1.InvokeRequired)
                {
                    AddMessageDelegate d = AddMessage;
                    richTextBox1.Invoke(d, message);
                }
                else
                {
                    richTextBox1.AppendText(message);
                }
            }
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
              
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(() => { AddMessage("aaa"); });
                th.IsBackground = true;
                th.Start();
            }
    
           
        }
    不过有一个问题需要注意——第一次(即Thread.Start之后调用那个AddMessage),此时InvokeRequired=true,此时使用Control.Invoke(……),那么方才InvokeRequired=false

    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年9月22日 3:28
    版主
  • 谢谢,我后来看了下委托和事件,我的理解如下,请帮忙参考是不是对的:

     private delegate delAaa(string msg);
    public void addMsg(string msg)
    {
       if (textbox1.invokeRequired)
        {
           delAaa d = addMsg;
           textbox1.Invoke(d,msg);  //此处只是在创建textbox1的线程中启动委托方法addMsg();
        }
        else
          textbox1.AppendText(msg); // /该adMsg方法在创建textbox1的线程被调用,执行把msg加到textbox1中去
    }
    Poly(175261789)  22:18:03
    是这样的吧,即该addMsg()先在其他线程中被调用,然后在控件线程被再次调用,被执行2次。

    2012年9月23日 2:35