Je suis complètement perplexe avec la façon dont ma file d'attente est fonction. Je tente (et échoue) d'écrire une petite application multithread pour collecter et afficher des données en C#. Après avoir lu Albahari's book et en utilisant le modèle Consumer/Producer , il décrit que j'ai obtenu la plupart de travail, sauf que mes données semblent être brouillées dans la file d'attente . Avant de file d'attente les champs de mon objet ont les valeurs suivantesPourquoi en C# est la file d'attente brouillant les données dans ses éléments?
timeStamp = 6
données [] = {4936, 9845, 24125, 44861}
Après avoir été dequeued les données ressemble
timeStamp = 6
données [] = {64791, 19466, 47772, 65405}
Je ne comprends pas pourquoi les valeurs dans les données archivées sont modifiées après la dequeue? Je suis perplexe, alors j'ai pensé que je le lancerais là-bas pour voir si quelqu'un peut me diriger dans la bonne direction pour corriger cela ou pour me diriger dans une direction différente pour continuer.
pertinentes du Code
objet personnalisé pour le stockage des données
objets pertinents et champs. La classe sensorData est une classe séparée utilisée pour stocker mes calculs. Les champs suivants sont utilisés pour configurer la file d'attente et les signaux entre les files d'attente de mise en file d'attente et de file d'attente de mise en file d'attente.
EventWaitHandle wh = new AutoResetEvent(false);
Queue<sensorData> dataQ = new Queue<sensorData>();
object locker = new object();
Enqueue Méthode/Discussion
Ceci est mon thread de travail il calcule quatre sinusoïdes et les files d'attente le résultat pour le traitement. J'écris aussi les résultats dans un fichier, donc je sais ce qu'il a calculé.
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();
}
ligne de l'exemple dans le fichier de sortie QueuedDataTest.txt
6, 4936, 9845, 24125, 44861,
Dequeue Méthode données
Cette La méthode supprime les éléments de la file d'attente et les écrit dans un fichier. Jusqu'à ce qu'un élément nul soit trouvé dans la file d'attente à quel point le travail est terminé.
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();
}
}
résultat de sortie après dequeueing les données et écrire dans DequeueDataTest.txt
6, 64791, 19466, 47772, 65405,
mises à jour 1 :
Emplacement des verrous dans le code actuel.
J'ai modifié le code pour placer des verrous autour des données d'écriture dans le fichier. Les blocs de code que j'ai verrouillés sont les suivants.
Dans le CalculateAndEnqueueData() méthode Je
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();
}
Dans le dequeueDataMethod() J'ai deux zones avec des serrures la première est ici
lock(locker)
if (dataQ.Count > 0)
{
data = dataQ.Dequeue();
if (data == null)
{
sw.Close();
return;
}
}
que je suppose que les serrures casier pour le code dans le bloc si. La deuxième est où j'écris le dans le fichier ici
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();
}
C'est tout.
Sûrement que vous pouvez faire le chemin de code, de manière plus simple et de démontrer encore le problème que vous êtes voyant. –
vous verrouillez la file d'attente, mais où est la synchronisation sur votre StreamWriter ??? –
Chaque thread écrit dans un fichier séparé. Donc je ne pensais pas que j'aurais besoin de synchronisation pour cette partie du fil. Ai-je tort? – Azim