C#多线程发送数据给PLC

Tony_Xian 2017-09-08 11:39:08
开三个线程,每个线程有7个PLC地址,如果先用一个线程往7个地址发送数据,则这个线程可以发送成功,然后再用其余两个线程给PLC发送数据,则发送失败,失败是指没有数据发过去,即PLC收不到数据,坐等大神帮小弟分析下原因,地址是没有错的
...全文
1483 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
无情时尚 2017-09-11
  • 打赏
  • 举报
回复
加了一个TCP的客户端发送



using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace PLCTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void butTh1Open_Click(object sender, EventArgs e)
{
//线程一
new Thread(() =>
{
UdpSend("192.168.1.55", 4567, "UDP线程一发送数据");
//TCPSend("192.168.1.55", 4567, "TCP线程一发送数据");
})
{ IsBackground = true }.Start();
}

private void butTh2Open_Click(object sender, EventArgs e)
{
//线程二
new Thread(() =>
{
UdpSend("192.168.1.55", 4567, "UDP线程二发送数据");
//TCPSend("192.168.1.55", 4567, "TCP线程二发送数据");
})
{ IsBackground = true }.Start();
}

private void butTh3Open_Click(object sender, EventArgs e)
{
//线程三
new Thread(() =>
{
UdpSend("192.168.1.55", 4567, "UDP线程三发送数据");
//TCPSend("192.168.1.55", 4567, "TCP线程三发送数据");
})
{ IsBackground = true }.Start();
}

private void UdpSend(string ipAddress, int port, string content)
{
UdpClient udp = new UdpClient(ipAddress, port);

byte[] data = Encoding.Default.GetBytes(content);

UpdateTextBox(textBox1, udp.Send(data, data.Length) > 0 ? "UDP发送数据成功" : "UDP发送数据失败");

if (udp != null) udp.Close();
}

private void TCPSend(string ipAddress, int port, string content)
{
TcpClient client = null;
try
{
client = new TcpClient(ipAddress, port);

byte[] data = Encoding.Default.GetBytes(content);

if (client.Connected)
{
NetworkStream stream = client.GetStream();
client.ReceiveTimeout = 3000;
stream.Write(data, 0, data.Length);
UpdateTextBox(textBox1, "TCP发送数据成功");
//这里没有做TCP的服务端
}

}
catch (Exception)
{
UpdateTextBox(textBox1, "TCP发送数据失败");
}
finally { if (client != null) client.Close(); }

}
private void UpdateTextBox(TextBox sender, string content)
{
//因为开线程,所以用委托更新界面
new Action(() =>
{
this.Invoke(new Action(() =>
{
sender.AppendText(content + Environment.NewLine);
}));
}).Invoke();
}
}
}
mk_lucifer 2017-09-11
  • 打赏
  • 举报
回复
代码都没有,肯定是你写错了被,通讯失败都有错误码,错误码也没有。 思路有问题,框架很重要。 很多组态软件的通讯源码是公开的,你可以去参考下怎么写,你这个思路本身就是有问题的。 设备抽象,协议抽象,数据包分发,变量映射,优先级,和线程没有关系,都有异步操作,单线程也可以得心应手。你这么做就是在制造不安全因素,制造混乱,多线程操作同一个IO,本身就不合适,。 设备组态最基本的,通道(IO,比如TCP)->设备组态(描述设备信息和协议等信息,变量映射或者其他的基本信息)->设备驱动(从队列获取IO数据包解析成特定协议报文,通过通道发送)->实时数据的变量映射(通过变量change,定时器等事件生成数据报文,更新变量值,发送给设备驱动,总之是个总调度)。 到变量这一层之后就是随意和前台交互了。
无情时尚 2017-09-11
  • 打赏
  • 举报
回复
其实是一样的,换种通讯方式而已,我这里用UDP方式,如果你是TCP的就自己写



using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace PLCTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void butTh1Open_Click(object sender, EventArgs e)
{
//线程一
new Thread(() =>
{
UdpSend("192.168.1.55", 4567, "线程一发送数据");
})
{ IsBackground = true }.Start();
}

private void butTh2Open_Click(object sender, EventArgs e)
{
//线程二
new Thread(() =>
{
UdpSend("192.168.1.55", 4567, "线程二发送数据");
})
{ IsBackground = true }.Start();
}

private void butTh3Open_Click(object sender, EventArgs e)
{
//线程三
new Thread(() =>
{
UdpSend("192.168.1.55", 4567, "线程三发送数据");
})
{ IsBackground = true }.Start();
}

private void UdpSend(string ipAddress, int port, string content)
{
UdpClient udp = new UdpClient(ipAddress, port);

byte[] data = Encoding.Default.GetBytes(content);

UpdateTextBox(textBox1, udp.Send(data, data.Length) > 0 ? "发送数据成功" : "发送数据失败");

if (udp != null) udp.Close();
}

private void UpdateTextBox(TextBox sender, string content)
{
//因为开线程,所以用委托更新界面
new Action(() =>
{
this.Invoke(new Action(() =>
{
sender.AppendText(content + Environment.NewLine);
}));
}).Invoke();
}
}
}
dy00544 2017-09-11
  • 打赏
  • 举报
回复
为啥一定要多线程? 单线程一样可以做好的。
Tony_Xian 2017-09-10
  • 打赏
  • 举报
回复
引用 3 楼 yuhijk2055 的回复:
简单调试了一下,没有问题
using System;
using System.IO.Ports;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace PLCTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void butTh1Open_Click(object sender, EventArgs e)
        {
            //线程一
            new Thread(() =>
            {
                ComSend("COM2");
            })
            {IsBackground = true}.Start();
        }

        private void butTh2Open_Click(object sender, EventArgs e)
        {
            //线程二
            new Thread(() =>
            {
                ComSend("COM3");
            })
            { IsBackground = true }.Start();
        }

        private void butTh3Open_Click(object sender, EventArgs e)
        {
            //线程三
            new Thread(() =>
            {
                ComSend("COM4");
            })
            { IsBackground = true }.Start();
        }

        private void ComSend(string com)
        {
            System.IO.Ports.SerialPort sp = null;
            sp = new System.IO.Ports.SerialPort();
            sp.PortName = com;
            sp.BaudRate = 9600;
            sp.DataBits = 8;
            sp.StopBits = StopBits.One;
            sp.ReadTimeout = 500;

            if (!sp.IsOpen) sp.Open();

            if (sp.IsOpen)
            {
                Byte[] Buf = Encoding.Default.GetBytes(com);
                sp.Write(Buf, 0, Buf.Length);
                UpdateTextBox(textBox1, "发送数据" + com);
                sp.Close();
            }
        }

        private void UpdateTextBox(TextBox sender, string content)
        {
            //因为开线程,所以用委托更新界面
            new Action(() =>
            {
                this.Invoke(new Action(() =>
                {
                    sender.AppendText(content + Environment.NewLine);
                }));
            }).Invoke();
        }
    }
}
我用的是网线通讯
无情时尚 2017-09-09
  • 打赏
  • 举报
回复



简单调试了一下,没有问题
using System;
using System.IO.Ports;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace PLCTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void butTh1Open_Click(object sender, EventArgs e)
{
//线程一
new Thread(() =>
{
ComSend("COM2");
})
{IsBackground = true}.Start();
}

private void butTh2Open_Click(object sender, EventArgs e)
{
//线程二
new Thread(() =>
{
ComSend("COM3");
})
{ IsBackground = true }.Start();
}

private void butTh3Open_Click(object sender, EventArgs e)
{
//线程三
new Thread(() =>
{
ComSend("COM4");
})
{ IsBackground = true }.Start();
}

private void ComSend(string com)
{
System.IO.Ports.SerialPort sp = null;
sp = new System.IO.Ports.SerialPort();
sp.PortName = com;
sp.BaudRate = 9600;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
sp.ReadTimeout = 500;

if (!sp.IsOpen) sp.Open();

if (sp.IsOpen)
{
Byte[] Buf = Encoding.Default.GetBytes(com);
sp.Write(Buf, 0, Buf.Length);
UpdateTextBox(textBox1, "发送数据" + com);
sp.Close();
}
}

private void UpdateTextBox(TextBox sender, string content)
{
//因为开线程,所以用委托更新界面
new Action(() =>
{
this.Invoke(new Action(() =>
{
sender.AppendText(content + Environment.NewLine);
}));
}).Invoke();
}
}
}
cyzclwan 2017-09-08
  • 打赏
  • 举报
回复
。这不贴点代码吗
大鱼> 2017-09-08
  • 打赏
  • 举报
回复
上位机软件啊,这个还是需要你贴出你的通讯核心代码的。

110,536

社区成员

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

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

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