Note that there are some explanatory texts on larger screens.

plurals
  1. POSync two BackgroundWorkers
    primarykey
    data
    text
    <p>I'm writing a C# wrapper, to a hardware controller using its <a href="http://en.wikipedia.org/wiki/Modbus" rel="nofollow">Modbus</a> protocol.<br> The controller has 12 inputs and 12 outputs.</p> <p>The wrapper has two tasks:<br> 1. Polling the controller's inputs at a constant interval (i.e. 50ms).<br> 2. Running preconfigured sequences, which changes the controller's outputs.</p> <p>The sequence is XML based: </p> <pre><code>&lt;opcode&gt; &lt;register&gt;0&lt;/register&gt; &lt;bit&gt;1&lt;/bit&gt; &lt;duration&gt;500&lt;/duration&gt; &lt;/opcode&gt; &lt;opcode&gt; &lt;register&gt;0&lt;/register&gt; &lt;bit&gt;0&lt;/bit&gt; &lt;duration&gt;0&lt;/duration&gt; &lt;/opcode&gt; .... </code></pre> <p>In the above sample, the controller should turn output #0 On and after 500ms turns it Off.<br> The pauses between operations was achieved using <code>Thread.Sleep()</code>.<br> In the past I've used just one BackgroundWorker. When not running the sequence it did the polling.</p> <p><strong>The challenge:</strong><br> The new demand for the wrapper is that it could detect changes in the controller's inputs while running a sequence.<br> I've modified the wrapper to have 2 backgroundworkers, one for polling and the other for setting the output registers.<br> Each of the BackgroundWorkers calls a seperate function on the controller, they do not try to access each other data nor they share any data.</p> <p><strong>Current code:</strong></p> <pre><code>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; } </code></pre> <p><strong>The problem:</strong><br> It's seems like the two BackgroundWorkers interfere with each other. I've tried using <code>Semaphore</code>, <code>Monitor.Wait()</code> and <code>ManualResetEvent.WaitOne()</code> but the BackgroundWorker, which deals with the sequences, doesn't handles them well. The main issue - its sleep duration is not consistent as before.</p> <p>Any advice will be welcome.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload