有没有人用过三菱PLC的通讯组件ACTPCCOM.DLL
函数原型:int ReadDeviceBlock(string szDevice, int lSize, out int lplData)在VB.NET里调用没问题:
      Dim data(6) As Integer
      mCom.ReadDeviceBlock("D1000", 5, data(0))
这样没有问题,data(0) 到data(5)都有返回数据
data(0)=41
data(1)=12
data(2)=93
data(3)=24
data(4)=76
data(5)=0
在C#里调用有问题:
      int[] data = new int[6];
      mCOM.ReadDeviceBlock("D1000", 5, out data[0]);
只有data(0)有返回数据,其余都是0
data[0]=41
data[1]=0
data[2]=0
data[3]=0
data[4]=0
data[5]=0有能解决的,我再加分

解决方案 »

  1.   

    int ReadDeviceBlock(string szDevice, int lSize, out int[] lplData)
      

  2.   

    ACTPCCOM.DLL
    是三菱的,
    函数原型是int ReadDeviceBlock(string szDevice, int lSize, out int lplData)
    怎么能改成int ReadDeviceBlock(string szDevice, int lSize, out int[] lplData)?
      

  3.   

    有几个疑问:
    1、确认这是个COM组件?注册没有?直接引用到net工程里面?
    2、那个函数原型,是在那里看到的?在COM组件?还是引入到net工程看到的?
      

  4.   

    DLL是标准COM,在工程里引用了。
    我又测试了,问题出在用线程调用,但是还是没有找解决办法:
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private iMXComponent m_COM= MXComponentFactory.CreateComponent(); 
            private Thread reader;
            private void button1_Click(object sender, EventArgs e)
            {
                this.Text = m_COM.Open().ToString();            
            }
            void Form1_setText(string s)
            {
                if (this.InvokeRequired)
                {
                    setstr st = new setstr(Form1_setText);
                    this.Invoke(st, new object[] {s});
                    return;
                }
                textBox1.Text = s;
            }
            private void button2_Click(object sender, EventArgs e)//直接读,没有问题
            {
                short[] data = new short[6];
                m_COM.ReadDeviceBlock2("D1000", 6, out data[0]);//从PLC:D1000开始连续读六个字元件
                textBox1.Text = "";
                for (int i = 0; i < 6; i++)
                {
                    textBox1.Text = textBox1.Text + data[i].ToString() + "\r\n";
                }
            }
    //读出结果如下:
    //data(0)=41
    //data(1)=12
    //data(2)=93
    //data(3)=24
    //data(4)=76
    //data(5)=0        private delegate void setstr(string s);
            private event setstr setText;
            private object obj1 = new object();
            private void read()//线程里读,有问题,只能读到第一个元件的数值,其余为0
            {
                short[] data = new short[6];
                string sData = "";
                m_COM.ReadDeviceBlock2("D1000", 6, out data[0]);//从PLC:D1000开始连续读六个字元件
                for (int i = 0; i < 6; i++)
                {
                    sData = sData + data[i].ToString() + "\r\n";
                }
                if (setText != null) setText(sData);
            }
    //读出结果如下:
    //data(0)=41
    //data(1)=0
    //data(2)=0
    //data(3)=0
    //data(4)=0
    //data(5)=0        private void timer1_Tick(object sender, EventArgs e)//定时器读,没有问题
            {
                short[] data = new short[6];
                string sData = "";
                m_COM.ReadDeviceBlock2("D1000", 6, out data[0]);//从PLC:D1000开始连续读六个字元件
                for (int i = 0; i < 6; i++)
                {
                    sData = sData + data[i].ToString() + "\r\n";
                }
                textBox1.Text = sData;
            }
    //读出结果如下:
    //data(0)=41
    //data(1)=12
    //data(2)=93
    //data(3)=24
    //data(4)=76
    //data(5)=0
            private void button4_Click(object sender, EventArgs e)//启动线程
            {
                if (this.Text == "0")
                {
                    reader = new Thread(read);
                    reader.IsBackground = true;
                    isRun = true;
                    setText += new setstr(Form1_setText);
                    reader.Start();
                }
            }
        }
      

  5.   

    谁知道是什么原因,.net 的bug吗?
      

  6.   

    问题在于COM的跨单元调用。因为位于相同单元的COM调用中的数组使用了锁定作为优化,这时out data[0]相当于传入了数组首地址,而在不使用代理的情况下,COM的跨单元调用则还原了封送单个字节的原始行为
    VS2005主窗口线程默认是STA,VS2010默认是MTA,可以使用STAThreadAttribute或MTAThreadAttribute更改默认单元设置
    对于工作线程的解决方法是在线程启动前使用Thread.SetApartmentState设置与COM相同的线程单元,避免COM的跨单元调用