我正在使用其Modbus协议向硬件控制器编写 C# 包装器。
控制器有 12 个输入和 12 个输出。
包装器有两个任务:
1. 以恒定的时间间隔(即 50 毫秒)轮询控制器的输入。
2. 运行预先配置的序列,这会改变控制器的输出。
该序列是基于 XML 的:
<opcode>
<register>0</register>
<bit>1</bit>
<duration>500</duration>
</opcode>
<opcode>
<register>0</register>
<bit>0</bit>
<duration>0</duration>
</opcode>
....
在上面的示例中,控制器应打开输出#0 并在 500 毫秒后将其关闭。
操作之间的暂停是使用Thread.Sleep()
.
过去我只使用了一个 BackgroundWorker。当不运行序列时,它会进行轮询。
挑战:
对包装器的新需求是它可以在运行序列时检测控制器输入的变化。
我已将包装器修改为具有 2 个后台工作程序,一个用于轮询,另一个用于设置输出寄存器。
每个 BackgroundWorkers 在控制器上调用一个单独的函数,它们不会尝试访问彼此的数据,也不会共享任何数据。
当前代码:
private void workerSequence_DoWork(object sender, DoWorkEventArgs e)
{
if (!terminating)
if (e.Argument != null)
DoSequence(e);
}
private void workerPoll_DoWork(object sender, DoWorkEventArgs e)
{
if (!terminating)
{
DoPoll();
Thread.Sleep(pollInterval);
}
}
private void DoSequence(DoWorkEventArgs e)
{
string sequenceName = e.Argument.ToString();
foreach (configurationSequencesSequenceOpcode opcode in sequencesList[sequenceName])
{
if (workerSequence.CancellationPending)
break;
byte register = opcode.register;
bool bit = opcode.bit;
int duration = opcode.duration;
SetRegister(register, bit, false);
Thread.Sleep(duration);
}
e.Result = e.Argument;
}
问题:
这两个 BackgroundWorker 似乎相互干扰。我试过使用Semaphore
,但是处理序列Monitor.Wait()
的ManualResetEvent.WaitOne()
BackgroundWorker 不能很好地处理它们。主要问题 - 它的睡眠时间与以前不一致。
欢迎任何建议。