我在从一个设备获取消息,这个消息的内容有好多种内容,现在我把获取消息专门写在一个类下面假设叫getMsg;我现在需要将获取到的消息分别对应的赋给我的一个Form窗体的label控件上,这个要用到事件委托,多线程知识,我在网上查了查资料,感觉不具有针对性,请大家来帮忙了,给点思路,最好附上代码,这个用到线程知识的,跨线程操作,如何将我的getMsg类里获取到的值赋值给Form界面的控件上呢,谢谢大家!

解决方案 »

  1.   

    .NET WinForm中 一个 跨线程访问控件的示例using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;namespace DelegateSample
    {
    /*********************************************************************
    * 2009-10-29 guog,老鸟绕道!
    * 跨线程控件访问示例:
    * 因为.NET2.0以后禁止对控件跨线程访问,
    * 所以可以使用委托来实现。
    * 这是其中一种方法
    *********************************************************************/
    /// <summary>
    /// 这里声明一个委托供线程调用
    /// </summary>
    /// <param name="txt"></param>
    public delegate void AppendTextHandler(string txt);public partial class Form1 : Form
    {
    Thread m_trd = null;
    //实例化一个委托对象
    AppendTextHandler m_handler = null;public Form1()
    {
    InitializeComponent();
    }/// <summary>
    /// 窗体Load 事件
    /// </summary>
    /// <param name="e"></param>
    protected override void OnLoad(EventArgs e)
    {
    base.OnLoad(e);
    //实例化一个委托对象
    m_handler = new AppendTextHandler(AppendTextText);//开启新线程
    m_trd = new Thread(new ThreadStart(OtherThreadDoSomething));
    m_trd.Start();
    }/// <summary>
    /// 关闭窗体时结束创建的线程
    /// </summary>
    /// <param name="e"></param>
    protected override void OnClosed(EventArgs e)
    {
    base.OnClosed(e);
    if (m_trd != null)
    {
    m_trd.Abort();
    }
    }/// <summary>
    /// 线程执行的方法
    /// </summary>
    private void OtherThreadDoSomething()
    {
    string _str;
    while (Thread.CurrentThread.ThreadState!=ThreadState.Aborted)
    {//线程未请求终止就一直执行
    _str = System.Guid.NewGuid().ToString();
    AppendTextText(_str);
    Thread.Sleep(50);//可去掉
    }
    }/// <summary>
    /// 向当前窗体控件中增加文本
    /// </summary>
    /// <param name="txt"></param>
    private void AppendTextText(string txt)
    {
    if (this.richTextBox1.InvokeRequired)
    {//调用方在另外一个线程中
    //在拥有此控件的线程上执行委托指向的方法
    this.richTextBox1.Invoke(m_handler, txt);
    }
    else
    {//调用方在当前线程中
    this.richTextBox1.AppendText(txt + "\r\n");//增加文本
    this.richTextBox1.ScrollToCaret();//滚动到当前目录
    }
    }
    }
    }
      

  2.   

     Form1
    {
    public delegate void mydelegate(string text);//定义一个委托 
            public static event mydelegate myevent;
                   private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                if (myevent != null)
                {
                    myevent(this.listBox1.SelectedItem.ToString());            } 
            }}
     public Form2()
            {
                InitializeComponent();
                Form1.myevent += new Form1.mydelegate(fm2_myevent);
            }
            void fm2_myevent(string str)
            {
                this.listBox1.Items.Add(str);        }
      

  3.   

    WindowsApplication1.CheckForIllegalCrossThreadCalls = false;
    InitializeComponent();
    写这个试试
      

  4.   

    C# WinForm开发系列 - Thread/Delegate/Event
      

  5.   

    用委托,下面是个简单的例子private delegate void FlushClient();//代理
             private void Form1_Load(object sender, EventArgs e)
            {
                Thread thread = new Thread(CrossThreadFlush);
                thread.IsBackground = true;
                thread.Start();
            }        private void CrossThreadFlush()
            {
                while (true)
                {
                    Thread.Sleep(1000);
                    ThreadFunction();
                }
            }
            private void ThreadFunction()
            {
               if (this.textBox1.InvokeRequired)
                {
                    FlushClient fc = new FlushClient(ThreadFunction);
                    this.Invoke(fc);
                }
                else
                {
                    this.textBox1.Text = DateTime.Now.ToString();
                }
            }
      

  6.   


    每次都 new 一个,感觉不太好吧!
      

  7.   

     label1 .BeginInvoke  (new MethodInvoker ( delegate (){ label1.Text = i.ToString ();}));一句话就可以了 ,i.ToString ()换成你要赋的值原理你看这里的blog
    http://www.cnblogs.com/joechen/archive/2009/04/28/1445425.html
      

  8.   


    当然,代码可以写的很简单,但是写的较为规范或高效还是要费一番功夫的。
    if (this.richTextBox1.InvokeRequired)//这个判断比较关键。
    {//调用方在另外一个线程中
    //在拥有此控件的线程上执行委托指向的方法
    this.richTextBox1.Invoke(m_handler, txt);//这里其实是在调用方法自身。
    }
    else
    {//调用方在当前线程中
    this.richTextBox1.AppendText(txt + "\r\n");//增加文本
    this.richTextBox1.ScrollToCaret();//滚动到当前目录
    }
      

  9.   

    三种方式
    1.直接开新Thread,不推荐,这种方式非线程安全,要用必须把 Form.CheckForIllegalCrossThreadCalls=false
    2.异步委托,正如龙宜坡所举的例子
    3.BackgroundWorker组件,推荐可以看看微软MSDN的线程安全和非常线程安全那章例子,很全面
      

  10.   

    这个例子把以上3种线程安全与非线程安全的方式全写出来了    using System;
        using System.ComponentModel;
        using System.Threading;
        using System.Windows.Forms;    namespace winform_线程安全与非线程安全
        {
            public class Form1 : Form
            {
                // This delegate enables asynchronous calls for setting
                // the text property on a TextBox control.
                delegate void SetTextCallback(string text);            // This thread is used to demonstrate both thread-safe and
                // unsafe ways to call a Windows Forms control.
                private Thread demoThread = null;            // This BackgroundWorker is used to demonstrate the 
                // preferred way of performing asynchronous operations.
                private BackgroundWorker backgroundWorker1;            private TextBox textBox1;
                private Button setTextUnsafeBtn;
                private Button setTextSafeBtn;
                private Button setTextBackgroundWorkerBtn;            private System.ComponentModel.IContainer components = null;            public Form1()
                {
                    InitializeComponent();
                    //Form.CheckForIllegalCrossThreadCalls = false;
                }            protected override void Dispose(bool disposing)
                {
                    if (disposing && (components != null))
                    {
                        components.Dispose();
                    }
                    base.Dispose(disposing);
                }            // This event handler creates a thread that calls a 
                // Windows Forms control in an unsafe way.
                private void setTextUnsafeBtn_Click(
                    object sender,
                    EventArgs e)
                {
                    this.demoThread =
                        new Thread(new ThreadStart(this.ThreadProcUnsafe));                this.demoThread.Start();
                }            // This method is executed on the worker thread and makes
                // an unsafe call on the TextBox control.
                private void ThreadProcUnsafe()
                {
                    this.textBox1.Text = "This text was set unsafely.";
                    MessageBox.Show(this.textBox1.Text);
                }            // This event handler creates a thread that calls a 
                // Windows Forms control in a thread-safe way.
                private void setTextSafeBtn_Click(
                    object sender,
                    EventArgs e)
                {
                    this.demoThread =
                        new Thread(new ThreadStart(this.ThreadProcSafe));                this.demoThread.Start();
                }            // This method is executed on the worker thread and makes
                // a thread-safe call on the TextBox control.
                private void ThreadProcSafe()
                {
                    this.SetText("This text was set safely.");
                    MessageBox.Show(this.textBox1.Text);
                }            // This method demonstrates a pattern for making thread-safe
                // calls on a Windows Forms control. 
                //
                // If the calling thread is different from the thread that
                // created the TextBox control, this method creates a
                // SetTextCallback and calls itself asynchronously using the
                // Invoke method.
                //
                // If the calling thread is the same as the thread that created
                // the TextBox control, the Text property is set directly.             private void SetText(string text)
                {
                    // InvokeRequired required compares the thread ID of the
                    // calling thread to the thread ID of the creating thread.
                    // If these threads are different, it returns true.
                    if (this.textBox1.InvokeRequired)
                    {
                        SetTextCallback d = new SetTextCallback(SetText);
                        this.Invoke(d, new object[] { text });
                    }
                    else
                    {
                        this.textBox1.Text = text;
                    }
                }            // This event handler starts the form's 
                // BackgroundWorker by calling RunWorkerAsync.
                //
                // The Text property of the TextBox control is set
                // when the BackgroundWorker raises the RunWorkerCompleted
                // event.
                private void setTextBackgroundWorkerBtn_Click(
                    object sender,
                    EventArgs e)
                {
                    this.backgroundWorker1.RunWorkerAsync();
                }            // This event handler sets the Text property of the TextBox
                // control. It is called on the thread that created the 
                // TextBox control, so the call is thread-safe.
                //
                // BackgroundWorker is the preferred way to perform asynchronous
                // operations.            private void backgroundWorker1_RunWorkerCompleted(
                    object sender,
                    RunWorkerCompletedEventArgs e)
                {
                    this.textBox1.Text =
                        "This text was set safely by BackgroundWorker.";
                }            #region Windows Form Designer generated code            private void InitializeComponent()
                {
                    this.textBox1 = new System.Windows.Forms.TextBox();
                    this.setTextUnsafeBtn = new System.Windows.Forms.Button();
                    this.setTextSafeBtn = new System.Windows.Forms.Button();
                    this.setTextBackgroundWorkerBtn = new System.Windows.Forms.Button();
                    this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
                    this.SuspendLayout();
                    // 
                    // textBox1
                    // 
                    this.textBox1.Location = new System.Drawing.Point(12, 12);
                    this.textBox1.Name = "textBox1";
                    this.textBox1.Size = new System.Drawing.Size(240, 20);
                    this.textBox1.TabIndex = 0;
                    // 
                    // setTextUnsafeBtn
                    // 
                    this.setTextUnsafeBtn.Location = new System.Drawing.Point(15, 55);
                    this.setTextUnsafeBtn.Name = "setTextUnsafeBtn";
                    this.setTextUnsafeBtn.TabIndex = 1;
                    this.setTextUnsafeBtn.Text = "Unsafe Call";
                    this.setTextUnsafeBtn.Click += new System.EventHandler(this.setTextUnsafeBtn_Click);
                    // 
                    // setTextSafeBtn
                    // 
                    this.setTextSafeBtn.Location = new System.Drawing.Point(96, 55);
                    this.setTextSafeBtn.Name = "setTextSafeBtn";
                    this.setTextSafeBtn.TabIndex = 2;
                    this.setTextSafeBtn.Text = "Safe Call";
                    this.setTextSafeBtn.Click += new System.EventHandler(this.setTextSafeBtn_Click);
                    // 
                    // setTextBackgroundWorkerBtn
                    // 
                    this.setTextBackgroundWorkerBtn.Location = new System.Drawing.Point(177, 55);
                    this.setTextBackgroundWorkerBtn.Name = "setTextBackgroundWorkerBtn";
                    this.setTextBackgroundWorkerBtn.TabIndex = 3;
                    this.setTextBackgroundWorkerBtn.Text = "Safe BackgroundWorker Call";
                    this.setTextBackgroundWorkerBtn.Click += new System.EventHandler(this.setTextBackgroundWorkerBtn_Click);
                    // 
                    // backgroundWorker1
                    // 
                    this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
                    // 
                    // Form1
                    // 
                    this.ClientSize = new System.Drawing.Size(268, 96);
                    this.Controls.Add(this.setTextBackgroundWorkerBtn);
                    this.Controls.Add(this.setTextSafeBtn);
                    this.Controls.Add(this.setTextUnsafeBtn);
                    this.Controls.Add(this.textBox1);
                    this.Name = "Form1";
                    this.Text = "Form1";
                    this.ResumeLayout(false);
                    this.PerformLayout();            }            #endregion
                [STAThread]
                static void Main()
                {
                    Application.EnableVisualStyles();
                    Application.Run(new Form1());
                }        }
        }
      

  11.   

    如果你不加上Form.CheckForIllegalCrossThreadCalls=false ;
    点击第一个按钮。会出现以下异常
    线程间操作无效: 从不是创建控件“textBox1”的线程访问它。
      

  12.   

    这个
    原理性质的东西,都在我的blog里面,更好的办法,还是用我写的框架吧。
    http://www.cnblogs.com/healerkx/category/199400.html