Invoke参数计数不匹配,求大神指导!!!

兰峰如月 2013-10-30 03:43:50
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();

}


请求大神给指导指导,小弟是个新手啊!
...全文
364 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
多线程是异步执行的,它不会等你Program.listStationList添加Item的线程执行完了再去遍历添加下拉列表,你这种同步的写法肯定是有问题的。 个人觉得应该是要等所有的添加Item子线程执行完了之后才通知下拉列表把Item添加进去的
兰峰如月 2013-10-31
  • 打赏
  • 举报
回复
引用 22 楼 vb763305825 的回复:
StationData stationData = new StationData(strText);
改成
StationData stationData = new StationData(node);
不好意思又来麻烦你了,我使用了你的代码,功能是实现了,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;
        }
兰峰如月 2013-10-31
  • 打赏
  • 举报
回复
谢谢大家伙,问题解决了,分数不多,还望见谅!!!!
  • 打赏
  • 举报
回复
StationData stationData = new StationData(strText);
改成
StationData stationData = new StationData(node);
  • 打赏
  • 举报
回复
改成这样应该没问题了
        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);
        }
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 19 楼 cncnm 的回复:
定时器你用System.Time.Timer 放外面不行么? 或者再开一个线程 上面那个错误"从不是创建控件..." 把线程设为:thread.ApartmentState = ApartmentState.STA;
我测试过不用xml参数的创建线程的label,一开始也是这个错误提示,我使用了Invoke后就可以了,现在我想把XML的值传到label里面,结果就不行了。每个label里面其实是一个监测站的数据,要让每个检测站是独立的。
菜菜菜菜鸟 2013-10-30
  • 打赏
  • 举报
回复
定时器你用System.Time.Timer 放外面不行么? 或者再开一个线程 上面那个错误"从不是创建控件..." 把线程设为:thread.ApartmentState = ApartmentState.STA;
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 17 楼 cncnm 的回复:
引用 15 楼 u012238529 的回复:
[quote=引用 14 楼 cncnm 的回复:] [quote=引用 13 楼 u012238529 的回复:] [quote=引用 12 楼 cncnm 的回复:] [quote=引用 9 楼 u012238529 的回复:] [quote=引用 8 楼 caozhy 的回复:] 最外面再加一个new Action(...)
貌似还是不行!
Thread th = new Thread(new ThreadStart(()=>{ Run(); })); public void Run() { this.Invoke(new Action(()=>{ 方法体...})); }[/quote]方法体是哪个方法体,是Set_labelText吗?麻烦了。[/quote] 不明白你这个程序 为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread [/quote]大体上就是在面板上生成一个个label,而一个线程包含一个label,label里的数据就是xml的,所以现在想把xml的值传到线程里的label中,不知道这样说你明白不?[/quote] 你这个写法不对,你把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 可能有点错误 [/quote]定时器是刷新label里面的数据的,但是label也得是一个独立的线程,所以我这么做的。不过现在搞不定了。
菜菜菜菜鸟 2013-10-30
  • 打赏
  • 举报
回复
引用 15 楼 u012238529 的回复:
引用 14 楼 cncnm 的回复:
[quote=引用 13 楼 u012238529 的回复:] [quote=引用 12 楼 cncnm 的回复:] [quote=引用 9 楼 u012238529 的回复:] [quote=引用 8 楼 caozhy 的回复:] 最外面再加一个new Action(...)
貌似还是不行!
Thread th = new Thread(new ThreadStart(()=>{ Run(); })); public void Run() { this.Invoke(new Action(()=>{ 方法体...})); }[/quote]方法体是哪个方法体,是Set_labelText吗?麻烦了。[/quote] 不明白你这个程序 为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread [/quote]大体上就是在面板上生成一个个label,而一个线程包含一个label,label里的数据就是xml的,所以现在想把xml的值传到线程里的label中,不知道这样说你明白不?[/quote] 你这个写法不对,你把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 可能有点错误
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
我现在修改成了这样
 private void Run(XmlNode s) 
{
weituo.Invoke(s);
}
void StartThread(XmlNode x)
{
Thread threadtest = new Thread(new ThreadStart(() => { Run(x); }));
threadtest.Start();

}

刚才的问题解决了,可是又出现新的问题

我明显使用了委托和Invoke函数啊?
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 14 楼 cncnm 的回复:
引用 13 楼 u012238529 的回复:
[quote=引用 12 楼 cncnm 的回复:] [quote=引用 9 楼 u012238529 的回复:] [quote=引用 8 楼 caozhy 的回复:] 最外面再加一个new Action(...)
貌似还是不行!
Thread th = new Thread(new ThreadStart(()=>{ Run(); })); public void Run() { this.Invoke(new Action(()=>{ 方法体...})); }[/quote]方法体是哪个方法体,是Set_labelText吗?麻烦了。[/quote] 不明白你这个程序 为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread [/quote]大体上就是在面板上生成一个个label,而一个线程包含一个label,label里的数据就是xml的,所以现在想把xml的值传到线程里的label中,不知道这样说你明白不?
菜菜菜菜鸟 2013-10-30
  • 打赏
  • 举报
回复
引用 13 楼 u012238529 的回复:
引用 12 楼 cncnm 的回复:
[quote=引用 9 楼 u012238529 的回复:] [quote=引用 8 楼 caozhy 的回复:] 最外面再加一个new Action(...)
貌似还是不行!
Thread th = new Thread(new ThreadStart(()=>{ Run(); })); public void Run() { this.Invoke(new Action(()=>{ 方法体...})); }[/quote]方法体是哪个方法体,是Set_labelText吗?麻烦了。[/quote] 不明白你这个程序 为什么又是循环foreach 又是System.Threading.Timer 又是线程Thread
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 12 楼 cncnm 的回复:
引用 9 楼 u012238529 的回复:
[quote=引用 8 楼 caozhy 的回复:] 最外面再加一个new Action(...)
貌似还是不行!
Thread th = new Thread(new ThreadStart(()=>{ Run(); })); public void Run() { this.Invoke(new Action(()=>{ 方法体...})); }[/quote]方法体是哪个方法体,是Set_labelText吗?麻烦了。
菜菜菜菜鸟 2013-10-30
  • 打赏
  • 举报
回复
引用 9 楼 u012238529 的回复:
引用 8 楼 caozhy 的回复:
最外面再加一个new Action(...)
貌似还是不行!
Thread th = new Thread(new ThreadStart(()=>{ Run(); })); public void Run() { this.Invoke(new Action(()=>{ 方法体...})); }
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 10 楼 u012592437 的回复:
引用 3 楼 u012238529 的回复:
[quote=引用 1 楼 u012592437 的回复:] Invoke(weituo,new Object[1] {一个XMLNode参数})
不行啊,那个参数要在哪里定义啊?在Run()的括号里面吗?
是的。这个是用当前的线程调用这个委托,XMLNode参数就是你准备传给Set_labelText函数的那个参数(strText) 你也可以这样 weituo.Invoke(一个XMLNode参数) 就如同Set_labelText(一个XMLNode参数)[/quote]如果在Run(XmlNode d){}这样写的话,下面的线程函数就会报错,传object可以,我指导这是基类,难道是XmlNode的参数不能在线程中传吗?
capricciosoft 2013-10-30
  • 打赏
  • 举报
回复
引用 3 楼 u012238529 的回复:
引用 1 楼 u012592437 的回复:
Invoke(weituo,new Object[1] {一个XMLNode参数})
不行啊,那个参数要在哪里定义啊?在Run()的括号里面吗?
是的。这个是用当前的线程调用这个委托,XMLNode参数就是你准备传给Set_labelText函数的那个参数(strText) 你也可以这样 weituo.Invoke(一个XMLNode参数) 就如同Set_labelText(一个XMLNode参数)
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 8 楼 caozhy 的回复:
最外面再加一个new Action(...)
貌似还是不行!
threenewbee 2013-10-30
  • 打赏
  • 举报
回复
最外面再加一个new Action(...)
兰峰如月 2013-10-30
  • 打赏
  • 举报
回复
引用 5 楼 caozhy 的回复:
        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();
             
        }
盼着到1 2013-10-30
  • 打赏
  • 举报
回复
Invoke(weituo,new object[] { strText???});
加载更多回复(5)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧