我正在写一个C#包装,使用其Modbus协议的硬件控制器。
该控制器有12个输入和12个输出。同步两个BackgroundWorkers
包装有两个任务:
1.以恒定的间隔(即50ms)轮询控制器的输入。
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 On和将其关闭后500毫秒。
操作之间的暂停使用Thread.Sleep()
实现。
以前我只用过一个BackgroundWorker。当不运行序列时,它执行轮询。
挑战:
为包装的新要求是运行的序列,同时它可以检测控制器的输入的变化。
我已经修改包装有2个backgroundworkers,一个用于轮询,另一个用于设置输出寄存器。
每个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;
}
问题:
这似乎是两个BackgroundWorkers互相干扰。我试过使用Semaphore
,Monitor.Wait()
和ManualResetEvent.WaitOne()
,但处理序列的BackgroundWorker不能很好地处理它们。主要问题 - 睡眠持续时间与以前不一致。
任何建议将受到欢迎。
我会尝试在一个线程与状态机来解决这个问题。例如。创造一个大循环,它永远在里面运行,根据状态你需要做的是什么。发送一个序列,检查输出等。 –
他们如何“互相干扰”,为什么你需要同步? –
当仅使用一个线程时,我无法轮询输入寄存器,因为'Thread.Sleep()'函数会锁定它。我已经在上面添加了一些代码。 – toy4fun