Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy in C# is Queue scrambling the data in its elements?
    primarykey
    data
    text
    <p>I am completely perplexed with how my Queue is function. I am attempting (and failing) to write a small multi-threaded application to collect and display data in C#.<br> After reading through <a href="http://www.albahari.com/threading/" rel="nofollow noreferrer">Albahari's book</a> and using the Consumer/Producer pattern he describes I got most of it to work except my data seems to get scrambled in the queue. Before getting queued the fields in my object have the following values</p> <blockquote> <p>timeStamp = 6<br> data[] ={4936, 9845, 24125, 44861}</p> </blockquote> <p>After being dequeued the data looks like</p> <blockquote> <p>timeStamp = 6<br> data[] = {64791, 19466, 47772, 65405}</p> </blockquote> <p>I don't understand why the values in the data filed are being changed after the dequeue? I am perplexed so I thought I'd throw it out there to see if anyone can point me in the right direction to fixing this or to point me in a different direction to proceed. </p> <hr> <p><strong>Relevant Code</strong></p> <hr> <p><strong>Custom Object for data storage</strong></p> <p>Relevant objects and Fields. The class sensorData is a seperate class use to store my calculations. </p> <pre><code>public class sensorData { public const int bufSize = 4; public UInt16[] data = new UInt16[4]; public double TimeStamp = 0; public int timeIndex = 0; } </code></pre> <p>The following fields are used to setup the queue and signals between the enqueue and dequeue threads.</p> <pre><code>EventWaitHandle wh = new AutoResetEvent(false); Queue&lt;sensorData&gt; dataQ = new Queue&lt;sensorData&gt;(); object locker = new object(); </code></pre> <p><strong>Enqueue Method/Thread</strong></p> <p>This is my worker thread it calculates four Sine curves and queues the result for processing. I also write the results to a file so I know what it has calculated.</p> <pre><code>private void calculateAndEnqueueData(BackgroundWorker worker, DoWorkEventArgs e) { int j = 0; double time = 0; double dist; UInt16[] intDist = new UInt16[sensorData.bufSize]; UInt16 uint16Dist; // Frequencies of the four Sine curves double[] myFrequency = { 1, 2, 5, 10 }; // Creates the output file. StreamWriter sw2 = File.CreateText("c:\\tmp\\QueuedDataTest.txt"); // Main loop to calculate my Sine curves while (!worker.CancellationPending) { // Calculate four Sine curves for (int i = 0; i &lt; collectedData.numberOfChannels; i++) { dist = Math.Abs(Math.Sin(2.0 * Math.PI * myFrequency[i] * time); uint16Dist = (UInt16)dist; intDist[i] = uint16Dist; } // Bundle the results and Enqueue them sensorData dat = new sensorData(); dat.data = intDist; dat.TimeStamp = time; dat.timeIndex = j; lock (locker) dataQ.Enqueue(dat); wh.Set // Output results to file. sw2.Write(j.ToString() + ", "); foreach (UInt16 dd in dat.intData) { sw2.Write(dd.ToString() + ", "); } sw2.WriteLine(); // Increments time and index. j++; time += 1 / collectedData.signalFrequency; Thread.Sleep(2); } // Clean up sw2.Close(); lock (locker) dataQ.Enqueue(null); wh.Set(); sw2.Close(); } </code></pre> <p>Example line in the output file <strong>QueuedDataTest.txt</strong></p> <blockquote> <p>6, 4936, 9845, 24125, 44861,</p> </blockquote> <p><strong>Dequeue Data Method</strong></p> <p>This Method dequeues elements from the queue and writes them to a file. Until a null element is found on the queue at which point the job is done.</p> <pre><code> private void dequeueDataMethod() { StreamWriter sw = File.CreateText("C:\\tmp\\DequeueDataTest.txt"); while (true) { sensorData data = null; // Dequeue available element if any are there. lock (locker) if (dataQ.Count &gt; 0) { data = dataQ.Dequeue(); if (data == null) { sw.Close(); return; } } // Check to see if an element was dequeued. If it was write it to file. if (data != null) { sw.Write(data.timeIndex.ToString() + ", "); foreach (UInt16 dd in data.data) sw.Write(dd.ToString() + ", "); sw.WriteLine(); } else { wh.WaitOne(); } } </code></pre> <p>Output result after dequeueing the data and writing it to <strong>DequeueDataTest.txt</strong></p> <blockquote> <p>6, 64791, 19466, 47772, 65405,</p> </blockquote> <hr> <p><strong>Updates 1:</strong></p> <p><strong>Location of Locks in current code.</strong></p> <hr> <p>I have edited the code to place locks around the writing data to the file. So the code blocks I have locks around are as follows.</p> <p>In the <em>CalculateAndEnqueueData()</em> method I have</p> <pre><code>lock (locker) dataQ.Enqueue(dat); wh.Set lock(locker) { sw2.Write(j.ToString() + ", "); foreach (UInt16 dd in dat.intData) { sw2.Write(dd.ToString() + ", "); } sw2.WriteLine(); } </code></pre> <p>In the <em>dequeueDataMethod()</em> I have two areas with locks the first is here</p> <pre><code>lock(locker) if (dataQ.Count &gt; 0) { data = dataQ.Dequeue(); if (data == null) { sw.Close(); return; } } </code></pre> <p>which I assume locks locker for the code in the <em>if</em> block. The second is where I write the to the file here </p> <pre><code>lock (locker) { sw.Write(data.timeIndex.ToString() + ", "); foreach (UInt16 dd in data.intData) sw.Write(dd.ToString() + ", "); sw.WriteLine(); if (icnt &gt; 10) { sw.Close(); return; } this.label1.Text = dataQ.Count.ToString(); } </code></pre> <p>That's all of them.</p> <hr>
    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.
 

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