Я полностью озадачен тем, как работает моя очередь. Я пытаюсь (и не могу) написать
небольшое многопоточное приложение для сбора и отображения данных в C #.
После прочтения книги Албахари и использования Потребителя / Производителя
шаблон, который он описывает, я получил большую часть его для работы, за исключением того, что мои данные, кажется, зашифрованы в
очередь. Перед постановкой в очередь поля в моем объекте имеют следующие значения
timeStamp = 6
данные [] = {4936, 9845, 24125, 44861}
После удаления данных данные выглядят как
timeStamp = 6
данные [] = {64791, 19466, 47772, 65405}
Я не понимаю, почему значения в поле данных изменяются после удаления из очереди?
Я озадачен, поэтому подумал, что брошу это туда, чтобы посмотреть, сможет ли кто-нибудь указать мне правильное направление, чтобы исправить это, или указать мне другое направление, чтобы продолжить.
Соответствующий код
Пользовательский объект для хранения данных
Соответствующие объекты и поля. Класс sensorData - это отдельный класс, используемый для хранения моих вычислений.
public class sensorData
{
public const int bufSize = 4;
public UInt16[] data = new UInt16[4];
public double TimeStamp = 0;
public int timeIndex = 0;
}
Следующие поля используются для настройки очереди и сигналов между потоками очереди и очереди.
EventWaitHandle wh = new AutoResetEvent(false);
Queue<sensorData> dataQ = new Queue<sensorData>();
object locker = new object();
Метод постановки в очередь / Тема
Это мой рабочий поток, он вычисляет четыре кривые синуса и ставит в очередь результат для обработки.
Я также записываю результаты в файл, чтобы знать, что он рассчитал.
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 < 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();
}
Пример строки в выходном файле QueuedDataTest.txt
6, 4936, 9845, 24125, 44861,
Метод данных удаления из очереди
Этот метод удаляет элементы из очереди и записывает их в файл. Пока в очереди не будет найден нулевой элемент, и в этот момент задание будет выполнено.
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 > 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();
}
}
Вывод результата после удаления данных и записи их в DequeueDataTest.txt
6, 64791, 19466, 47772, 65405,
Обновления 1:
Местоположение замков в текущем коде.
Я отредактировал код, чтобы поместить блокировки вокруг записи данных в файл. Таким образом, блоки кода, которые у меня есть, выглядят следующим образом.
В методе CalculateAndEnqueueData () у меня есть
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();
}
В dequeueDataMethod () У меня есть две области с замками, первая здесь
lock(locker)
if (dataQ.Count > 0)
{
data = dataQ.Dequeue();
if (data == null)
{
sw.Close();
return;
}
}
, который, как я предполагаю, блокирует локер для кода в блоке if . Второй, где я пишу в файл здесь
lock (locker)
{
sw.Write(data.timeIndex.ToString() + ", ");
foreach (UInt16 dd in data.intData)
sw.Write(dd.ToString() + ", ");
sw.WriteLine();
if (icnt > 10)
{
sw.Close();
return;
}
this.label1.Text = dataQ.Count.ToString();
}
Это все из них.