Reputation: 459
In one of my applications I've created a sort of queue-list so that my application can send out midi-signals in the correct order.
So whenever I want to play a midi-note, I will add that midinote to a list.
I also have a backgroundworker running which will continuously check if there is note waiting in the "queue" and if there is, he will send it to the outputdevice.
Now I wanted to stresstest this, and 19 out of the 20 it works perfectly. Once every now and then, I get a nullexception error. The truth is that I don't know why it's giving me this error.
The only thing I can think of is that at the moment that the backgroundworker if checking if there is a note waiting in the queue, that there is a second argument which is still missing at that point which is why he trows an error.
However, when I look at the contents of the queue, it's all there.
So let me show you the code:
public class queueClass
{
public int note {get; set;}
public int delay { get; set; }
public queueClass(int selectedNote, int selectedDelay)
{
note = selectedNote;
delay = selectedDelay;
}
}
List<queueClass> midiQueue = new List<queueClass>();
public void playNote(int noteNumber, int delay)
{
if (Enabled)
{
// ADD THE NOTE TO THE QUEUE
midiQueue.Add(new queueClass(noteNumber, delay));
if (!bgwMidi.IsBusy)
{
bgwMidi.RunWorkerAsync();
Console.WriteLine(DateTime.Now + " >>> BACKGROUNDWORKER MIDI STARTED");
}
}
}
private void bgwMidi_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (worker.IsBusy)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
// CHECK IF THERE IS A MIDINOTE IN THE QUEUE
if (midiQueue != null && midiQueue.Count > 0)
{
if (midiQueue[0].note > -1 && midiQueue[0].delay > -1)
{
sendNote(midiQueue[0].note, midiQueue[0].delay);
}
}
}
}
}
The error is thrown on the first line of this code:
if (midiQueue[0].note > -1 && midiQueue[0].delay > -1)
{
sendNote(midiQueue[0].note, midiQueue[0].delay);
}
and it says:
Object reference not set to an instance of an object
However when I look at my midiQueue it holds the values:
delay: 0
note: 5
For now I've tried to bypass the error by putting it into a try-catch block, but I would like to know what is causing this issue.
Does anybody have an idea on this?
Thanks!
Upvotes: 0
Views: 77
Reputation: 1718
You should lock the midiqueue when Adding or removing items, if these operations are done in different threads.
When you push items:
lock (midiQueue) { midiQueue.Add(new queueClass(noteNumber, delay)); }
When you pop items:
lock (midiQueue) { /* the pop operation(s) */
When you use items:
lock (midiQueue)
{
if (midiQueue != null && midiQueue.Count > 0)
{
if (midiQueue[0].note > -1 && midiQueue[0].delay > -1)
sendNote(midiQueue[0].note, midiQueue[0].delay);
}
}
Upvotes: 4
Reputation: 2594
You check this :
midiQueue != null && midiQueue.Count > 0
So from there you know that you have an instanciated midiQueue and at least one element in midiQueue.
Then you do this :
midiQueue[0].note > -1 && midiQueue[0].delay > -1
And here is your problem. If midiQueue[0] is null then midiQueue[0].note will throw an "Object reference not set to an instance of an object" exception.
So you should modify your test :
if (midiQueue != null && midiQueue.Count > 0)
{
if (midiQueue[0] != null && midiQueue[0].note > -1 && midiQueue[0].delay > -1)
{
sendNote(midiQueue[0].note, midiQueue[0].delay);
}
}
Upvotes: 0