我的应用中需要对下位PLC的I/O口进行读写,我在程序中做了一个子窗口用于手动控制PLC的I/O。由于读写PLC的I/O时可能会阻塞主线程,我用System.Timers.Timer每500毫秒去读写I/O口,如果I/O口被触发则使用Invoke委托将子窗口对应的按钮背景颜色置为亮绿色。
部分代码如下:
在子窗口装载时定义定时器:
timerOutputAWrite = new System.Timers.Timer(500);
timerOutputAWrite.Elapsed += new System.Timers.ElapsedEventHandler(OutputAWrite);
timerOutputAWrite.AutoReset = true;
timerOutputAWrite.Enabled = true;
timerOutputARead = new System.Timers.Timer(500);
timerOutputARead.Elapsed += new System.Timers.ElapsedEventHandler(OutputARead);
timerOutputARead.AutoReset = true;
timerOutputARead.Enabled = true;
OutputAWrite函数如下:
private void OutputAWrite(object sender, System.Timers.ElapsedEventArgs e)
{
//设置控件按钮的状态
if (boolOutputA01 == true)
{
clientOutputAReadWrite.SetInt32Value(tagintOutputA01, 0, 1);
clientOutputAReadWrite.WriteTag(tagintOutputA01, DataTimeout);
}
else
{
clientOutputAReadWrite.SetInt32Value(tagintOutputA01, 0, 0);
clientOutputAReadWrite.WriteTag(tagintOutputA01, DataTimeout);
}
}
OutputARead函数如下
private void OutputARead(object sender, System.Timers.ElapsedEventArgs e)
{
//读取控件按钮的状态
if (!btnOutputA1.IsDisposed)
{
int intReadOutputA01 = clientOutputAReadWrite.ReadTag(tagintOutputA01, DataTimeout);
if (intReadOutputA01 == Libplctag.PLCTAG_STATUS_OK || intReadOutputA01 == Libplctag.PLCTAG_STATUS_PENDING)
{
intOutputA01Value = clientOutputAReadWrite.GetInt32Value(tagintOutputA01, 0);
}
Action<int> myUpdatebtnOutputA1 = delegate (int intoutputA01value)
{
if (intoutputA01value == 1)
{
btnOutputA1.BackColor = Color.Lime;
}
else
{
btnOutputA1.BackColor = Color.DarkGreen;
}
};
this.Invoke(myUpdatebtnOutputA1, intOutputA01Value);
}
}
子窗口关闭时的程序如下:
private void frmOutputASetup_FormClosing(object sender, FormClosingEventArgs e)
{
timerOutputAWrite.Enabled = false;
timerOutputAWrite.Dispose();
timerOutputARead.Enabled = false;
timerOutputARead.Dispose();
//将PLC中所有A相TAG置零
int intReadOutputA01 = clientOutputAReadWrite.ReadTag(tagintOutputA01, DataTimeout);
if (intReadOutputA01 == Libplctag.PLCTAG_STATUS_OK || intReadOutputA01 == Libplctag.PLCTAG_STATUS_PENDING)
{
intOutputA01Value = clientOutputAReadWrite.GetInt32Value(tagintOutputA01, 0);
}
if (intOutputA01Value == 1)
{
clientOutputAReadWrite.SetInt32Value(tagintOutputA01, 0, 0);
clientOutputAReadWrite.WriteTag(tagintOutputA01, DataTimeout);
}
btnOutputA1.BackColor = Color.DarkGreen;
}
现在子窗口关闭时在这句代码处 this.Invoke(myUpdatebtnOutputA1, intOutputA01Value);有时会报“无法访问已释放的对象”这个错误,我怀疑是子窗口关闭时System.Timers.Timer还在执行,可是我已经将Timer.Enabled置为false了啊!请问这个问题是什么原因造成的,怎么解决。谢谢!