C#上位机监控PLC通讯状态(多线程、异步、invoke使用技巧)
在实际的工程中一定要明白什么时候用多线程,什么时候用异步,只有这样才能解决窗口的卡顿感问题。新建一个测试工程:
添加S7.net通讯库
引用命名空间
using S7.net;
public partial class Form1:Form
{
//创建一个多线程,不能在主线程下一直占用。
Plc plc = new Plc(CpuType.S71500,"192.168.0.102",0,1);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender,EventArgs e)
{
Task task = new TaskFactory().StartNew(()=>
{
while(true)
{
if(!plc.IsConnected)
{
this.toolStripStatuesLabel1.Text="通讯异常";
this.toolStripStatuesLabel1.BackColor=Color.Red;
plc.Open();
}
if(plc.IsConnected)
{
this.toolStripStatuesLabel1.Text="通讯正常";
this.toolStripStatuesLabel1.BackColor=Color.Green;
bool b = (bool)plc.Read("DB9.DBX7.0");
}
}
});
}
}
编写以上代码运行后会提示报错,因为背景的操作是属于主线程的,而现在的操作Task是多线程下的
public partial class Form1:Form
{
Plc plc = new Plc(CpuType.S71500,"192.168.0.102",0,1);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender,EventArgs e)
{
//创建一个多线程,不能在主线程下一直占用。
Task task = new TaskFactory().StartNew(()=>
{
while(true)
{
this.Invoke(new Action(()=> //得写在循环内部否则会被一直占用,而没响应主线程了
{
if(!plc.IsConnected)
{
this.toolStripStatuesLabel1.Text="通讯异常";
this.toolStripStatuesLabel1.BackColor=Color.Red;
//写个异步函数,因为此处的打开操作是个耗时操作。
NewMethod();
}
if(plc.IsConnected)
{
this.toolStripStatuesLabel1.Text="通讯正常";
this.toolStripStatuesLabel1.BackColor=Color.Green;
//写个异步函数,因为此处的读取操作是个耗时操作。
NewMethod1();
}
}
}));
});
private async void NewMethod()
{
await Task.Run(()=>{
try{
plc.Open();
}catch
{}
}); //在PLC关闭的情况下打开会报错。
}
private async void NewMethod1()
{
await Task.Run(()=>{
try{
bool b = (bool)plc.Read("DB9.DBX7.0");
}catch
{
}
}); //在PLC在关闭的情况下读取的会报错。
}
}
}
多线程对主线程的操作必须写在Invoke体内。因为BackColor是主线程的