c#程序提示“参数计数不匹配”的问题记录(BeginInvoke和Invoke方法使用小例子)

在我的问题代码中,这个异常是由于BeginInvoke()里面的参数填写不对导致的。
首先描述一下我的代码功能(当然我现在是特地为了验证这个bug而写的小例子,所以大家放心,代码量很小):
c#程序提示“参数计数不匹配”的问题记录(BeginInvoke和Invoke方法使用小例子)_第1张图片
点击第“开始显示”按钮之后,就不停在listBox1中插入i = x并刷新界面显示,x一直从0到999,大概耗时4s左右。

主界面不停刷新listbox1的同时,我的子线程中需要进行一些耗时的操作,然后在主界面的listBox1上显示数据。

因为是在子线程中通过子类Class1发出消息eventShowData给主线程,然后主线程中的消息响应函数ShowAddData()里面调用lixtBox1,所以需要用BeginInvoke方法来操作listBox1(如果不用BeginInvoke方法的话,运行时会报“线程间操作无效: 从不是创建控件“listBox1”的线程访问它”的异常信息)
子类Class1代码如下:

using System.Threading;
namespace TestInvoke
{
    public delegate void DelegateShowAddResult(bool bShow);
    class Class1
    {
        public event DelegateShowAddResult eventShowData;
        public void ShowData()
        {
            Thread.Sleep(2000);
            eventShowData(true);
        }
    }
}

主界面代码如下:

using System;
using System.Threading;
using System.Windows.Forms;

namespace TestInvoke
{
    public partial class Form1 : Form
    {
        Class1 myClass;
        public Form1()
        {
            InitializeComponent();
            myClass = new Class1();
            myClass.eventShowData += ShowAddData;
        }
        private void ShowAddData(bool bShow)
        {
            if (listBox1.InvokeRequired)
            {
                listBox1.BeginInvoke(new DelegateShowAddResult(ShowAddData), bShow);
                Console.WriteLine("run code after BeginInvoke");
            }
            else
            {
                if (bShow)
                {
                    string str = "";
                    str = string.Format("ShowAddData:a+b = {0}", 100);
                    listBox1.Items.Insert(0, "childThread Insert data in listBox1");
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string str = "";
            for (int i = 0; i < 1000; i++)
            {
                str = string.Format("i = {0}", i);
                listBox1.Items.Insert(0, str);
                this.Refresh();
                Thread.Sleep(1);
            }
        }
        private void CallToChildThread()
        {
            myClass.ShowData();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Console.WriteLine("开启线程:");
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
        }
    }
}

上面这段代码已经是正常代码了,我之前犯错的时候就是在ShowAddData方法中的listBox1.BeginInvoke()这里面少加了,bShow这个参数,这个参数不加的话编译可以正常通过,但程序跑到这边的时候就会中断并报异常,异常界面如下:
c#程序提示“参数计数不匹配”的问题记录(BeginInvoke和Invoke方法使用小例子)_第2张图片
这种情况下不会提示是在哪一行代码出的问题,所以在代码量很多的情况下,我真的是非常抓狂,因此特意在这里记录一下自己的坑!!!

在这里,我顺便记录一下BeginInvoke和Invoke方法的区别,官方的解释如下:
BeginInvoke:在创建控件的基础句柄所在线程上,用指定的参数异步执行指定委托。
Invoke:在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。

官方解释是不是看的一愣一愣的?这TM看得出毛的区别啊?
通过实际测试,我记录一下这两者的区别:
看下面两种写法:
方式1:

listBox1.BeginInvoke(new DelegateShowAddResult(ShowAddData), bShow);
Console.WriteLine("run code after BeginInvoke");

方式2:

listBox1.Invoke(new DelegateShowAddResult(ShowAddData), bShow);
Console.WriteLine("run code after BeginInvoke");

当代码执行到listBox1.BeginInvoke()的时候,
方式1中ShowAddData()方法中的代码和Console.WriteLine(“run code after BeginInvoke”);会同时运行
而方式2中会等到ShowAddData()方法中的代码运行结束之后,才会继续运行Console.WriteLine(“run code after BeginInvoke”);

你可能感兴趣的:(C#,委托,BeginInvoke,参数计数不匹配)