public delegate void WeiTuo<XmlNode>(XmlNode s ); //定义委托
        private  WeiTuo<XmlNode> weituo;         //定义委托……
 private void frmMain_Load(object sender, EventArgs e){
            EQ2008Config.GetSection();
            string strpath = AppDomain.CurrentDomain.BaseDirectory + "\\StationConfig.xml";
            XmlDocument doc = new XmlDocument();//初始化一个xml实例
            doc.Load(strpath);//导入指定的xml文件
            XmlNode no = doc.SelectSingleNode("StationList");//指定一个节点
            XmlNodeList listnode = no.SelectNodes("StationData");  
            ti = new TimerCallback(ShowDataToScreenStation);   
            foreach (XmlNode node in listnode)//遍历所有的stationdata节点
            {
                weituo = new WeiTuo<XmlNode>(Set_labelText);//委托
                StartThread(node);
               
            }}
 public void Set_labelText(XmlNode strText) 
        {
            
            StationData stationData = new StationData(strText);
            //stationData.IsShow = false;
            Program.listStationList.Add(stationData);
            this.flowLayoutPanel1.BackColor = Color.Orange;
            Label lab = new Label();//实例一个label显示
           
            lab.Name = "lab" + stationData.CardFlagID.ToString();
            lab.AutoSize = false;
            lab.Size = new Size(280, 140);
            lab.BorderStyle = BorderStyle.Fixed3D;
            lab.Text = stationData.StatinName;
            lab.Font = new Font("宋体", 11);            if (stationData.IsShow)
            {
                lab.BackColor = Color.Green;
            }
            if (stationData.IsShow)
            {
                System.Threading.Timer tim = new System.Threading.Timer(ti, stationData.CardFlagID, 0, 10000);
                //超过0秒后,以及此后每隔10秒间隔,都会调用一次由TimerCallback(ShowDataToScreenStation)指定的委托。
                dicThread.Add(stationData.CardFlagID.ToString(), tim);            }
            this.flowLayoutPanel1.Controls.Add(lab);
        }
 private void Run() 
        {
            Invoke(weituo); //就是这里报错,参数计数不匹配  
        }
        void StartThread(XmlNode x)
        {
           // ParameterizedThreadStart ParStart = new ParameterizedThreadStart(Run);
              ThreadStart threadtest = new ThreadStart(Run);
      Thread threadNew=new Thread(threadtest);      
      threadNew.Start();
            
        }请求大神给指导指导,小弟是个新手啊!threaddelegatexmllabel遍历

解决方案 »

  1.   

    Invoke(weituo,new Object[1] {一个XMLNode参数})
      

  2.   

    Invoke(weituo);
    ->
    Invoke(new Action(() => weituo(这里传一个XmlNode)));
      

  3.   

    不行啊,那个参数要在哪里定义啊?在Run()的括号里面吗?
      

  4.   

            void StartThread(XmlNode x)
            {
               // ParameterizedThreadStart ParStart = new ParameterizedThreadStart(Run);
                  ThreadStart threadtest = new ThreadStart(() => (Invoke(new Action(() => weituo(x)))));
              Thread threadNew=new Thread(threadtest);      
              threadNew.Start();
                 
            }
      

  5.   

    Invoke(weituo,new object[] { strText???});
      

  6.   

    最外面再加一个new Action(...)
      

  7.   

    是的。这个是用当前的线程调用这个委托,XMLNode参数就是你准备传给Set_labelText函数的那个参数(strText)你也可以这样
    weituo.Invoke(一个XMLNode参数)就如同Set_labelText(一个XMLNode参数)
      

  8.   

    是的。这个是用当前的线程调用这个委托,XMLNode参数就是你准备传给Set_labelText函数的那个参数(strText)你也可以这样
    weituo.Invoke(一个XMLNode参数)就如同Set_labelText(一个XMLNode参数)如果在Run(XmlNode d){}这样写的话,下面的线程函数就会报错,传object可以,我指导这是基类,难道是XmlNode的参数不能在线程中传吗?
      

  9.   


    Thread th = new Thread(new ThreadStart(()=>{ Run(); }));
    public void Run()
    {
        this.Invoke(new Action(()=>{ 方法体...}));
    }
      

  10.   


    Thread th = new Thread(new ThreadStart(()=>{ Run(); }));
    public void Run()
    {
        this.Invoke(new Action(()=>{ 方法体...}));
    }方法体是哪个方法体,是Set_labelText吗?麻烦了。
      

  11.   


    Thread th = new Thread(new ThreadStart(()=>{ Run(); }));
    public void Run()
    {
        this.Invoke(new Action(()=>{ 方法体...}));
    }方法体是哪个方法体,是Set_labelText吗?麻烦了。不明白你这个程序  为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread 
      

  12.   


    Thread th = new Thread(new ThreadStart(()=>{ Run(); }));
    public void Run()
    {
        this.Invoke(new Action(()=>{ 方法体...}));
    }方法体是哪个方法体,是Set_labelText吗?麻烦了。不明白你这个程序  为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread 
    大体上就是在面板上生成一个个label,而一个线程包含一个label,label里的数据就是xml的,所以现在想把xml的值传到线程里的label中,不知道这样说你明白不?
      

  13.   

    我现在修改成了这样 private void Run(XmlNode s) 
            {
                weituo.Invoke(s);
            }
         void StartThread(XmlNode x)
            {
                Thread threadtest = new Thread(new ThreadStart(() => { Run(x); }));
                threadtest.Start();
                
            }
    刚才的问题解决了,可是又出现新的问题我明显使用了委托和Invoke函数啊?
      

  14.   


    Thread th = new Thread(new ThreadStart(()=>{ Run(); }));
    public void Run()
    {
        this.Invoke(new Action(()=>{ 方法体...}));
    }方法体是哪个方法体,是Set_labelText吗?麻烦了。不明白你这个程序  为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread 
    大体上就是在面板上生成一个个label,而一个线程包含一个label,label里的数据就是xml的,所以现在想把xml的值传到线程里的label中,不知道这样说你明白不?你这个写法不对,你把System.Threading.Timer(多线程定时器)放在循环里面,就是每次循环都创建一个定时器....定义一个线程就够了哇 
    object _lock = new object(); 
    Thread th = new Thread(){new ThreadStart(()=>{ object(lock(_lock){ foreach(...){ 
    读xml,创建lable,AddLable(lable) } })})};th.start();th,isPostBack=true; 
     public void AddLable(Lable l){this.Invoke(new Action(()=>{ 面板上添加lable }))}  
    没用VS  可能有点错误  
      

  15.   


    Thread th = new Thread(new ThreadStart(()=>{ Run(); }));
    public void Run()
    {
        this.Invoke(new Action(()=>{ 方法体...}));
    }方法体是哪个方法体,是Set_labelText吗?麻烦了。不明白你这个程序  为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread 
    大体上就是在面板上生成一个个label,而一个线程包含一个label,label里的数据就是xml的,所以现在想把xml的值传到线程里的label中,不知道这样说你明白不?你这个写法不对,你把System.Threading.Timer(多线程定时器)放在循环里面,就是每次循环都创建一个定时器....定义一个线程就够了哇 
    object _lock = new object(); 
    Thread th = new Thread(){new ThreadStart(()=>{ object(lock(_lock){ foreach(...){ 
    读xml,创建lable,AddLable(lable) } })})};th.start();th,isPostBack=true; 
     public void AddLable(Lable l){this.Invoke(new Action(()=>{ 面板上添加lable }))}  
    没用VS  可能有点错误  定时器是刷新label里面的数据的,但是label也得是一个独立的线程,所以我这么做的。不过现在搞不定了。
      

  16.   

    定时器你用System.Time.Timer 放外面不行么?  或者再开一个线程  
    上面那个错误"从不是创建控件..."  把线程设为:thread.ApartmentState = ApartmentState.STA;
      

  17.   

    我测试过不用xml参数的创建线程的label,一开始也是这个错误提示,我使用了Invoke后就可以了,现在我想把XML的值传到label里面,结果就不行了。每个label里面其实是一个监测站的数据,要让每个检测站是独立的。
      

  18.   

    改成这样应该没问题了
            void StartThread(XmlNode x)
            {
                new Thread(() => Set_labelText(x)).Start();
            }        public void Set_labelText(XmlNode strText)
            {
                this.Invoke((Action<XmlNode>)delegate(XmlNode node)
                {
                    StationData stationData = new StationData(strText);
                    //stationData.IsShow = false;
                    Program.listStationList.Add(stationData);
                    this.flowLayoutPanel1.BackColor = Color.Orange;
                    Label lab = new Label();//实例一个label显示                lab.Name = "lab" + stationData.CardFlagID.ToString();
                    lab.AutoSize = false;
                    lab.Size = new Size(280, 140);
                    lab.BorderStyle = BorderStyle.Fixed3D;
                    lab.Text = stationData.StatinName;
                    lab.Font = new Font("宋体", 11);                if (stationData.IsShow)
                    {
                        lab.BackColor = Color.Green;
                    }
                    if (stationData.IsShow)
                    {
                        System.Threading.Timer tim = new System.Threading.Timer(ti, stationData.CardFlagID, 0, 10000);
                        //超过0秒后,以及此后每隔10秒间隔,都会调用一次由TimerCallback(ShowDataToScreenStation)指定的委托。
                        dicThread.Add(stationData.CardFlagID.ToString(), tim);                }
                    this.flowLayoutPanel1.Controls.Add(lab);
                }, strText);
            }
      

  19.   

    StationData stationData = new StationData(strText);
    改成
    StationData stationData = new StationData(node);
      

  20.   

    不好意思又来麻烦你了,我使用了你的代码,功能是实现了,label也出现了,原来的代码是生成一个label,执行 Program.listStationList.Add(stationData);这段代码,然后遍历Program.listStationList,作用就是生成检查站(label)的下拉列表,但是现在这个功能没有了,我调试发现,Program.listStationList.Add(stationData);这句当中的list是有数据的, foreach (StationData m in Program.listStationList)里面也是有数据的,但是上面的遍历完后,listStationList就没有数据了,什么情况呢? private void frmMain_Load(object sender, EventArgs e)
            {
                EQ2008Config.GetSection();
                string strpath = AppDomain.CurrentDomain.BaseDirectory + "\\StationConfig.xml";
                XmlDocument doc = new XmlDocument();//初始化一个xml实例
                doc.Load(strpath);//导入指定的xml文件
                XmlNode no = doc.SelectSingleNode("StationList");//指定一个节点
                XmlNodeList listnode = no.SelectNodes("StationData");//获取同名同级别"stationdata"节点集合
                
                ti = new TimerCallback(ShowDataToScreenStation);
                //System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
                foreach (XmlNode node in listnode)//遍历所有的stationdata节点
                {                //Set_labelText(node);
                    weituo = new WeiTuo<XmlNode>(Set_labelText);
                    //wt = new WT_test(Test);
                    StartThread(node);
                   
                }
                //生成已经包含的检查站的下拉菜单
                foreach (StationData m in Program.listStationList)//这里在完成上面的遍历后,Program.listStationList没数据
                {
                    ToolStripMenuItem msta = new ToolStripMenuItem(m.StatinName);
                    msta.Tag = m.StatinName;
                    msta.Click += new EventHandler(新增检测站ToolStripMenuItem_Click);
                    this.检测站参数设置ToolStripMenuItem.DropDownItems.Add(msta);
                }
                this.timRefreshData_Tick(null, null);            开始发送正常数据ToolStripMenuItem_Click(null, null);
                FileInfo f = new FileInfo("StationConfig.xml");
                iStartDateXmlOLD = f.LastWriteTime.Ticks;
                f = new FileInfo("EQ2008_Dll_Set.ini");
                iIntDatexmlOLD = f.LastWriteTime.Ticks;            this.timer1.Enabled = true;
            }
      

  21.   

    多线程是异步执行的,它不会等你Program.listStationList添加Item的线程执行完了再去遍历添加下拉列表,你这种同步的写法肯定是有问题的。
     个人觉得应该是要等所有的添加Item子线程执行完了之后才通知下拉列表把Item添加进去的