C# 无法解释的空异常错误

C# 无法解释的空异常错误,c#,C#,在我的一个应用程序中,我创建了一种队列列表,以便我的应用程序能够以正确的顺序发送midi信号 因此,每当我想播放midi音符时,我都会将该midi音符添加到列表中 我还有一个backgroundworker在运行,它会不断检查“队列”中是否有票据等待,如果有,他会将其发送到outputdevice 现在我想对它进行压力测试,20个测试中有19个工作得很好。偶尔,我会收到一个nullexception错误。事实是,我不知道为什么它会给我这个错误 我能想到的唯一一件事是,当backgroundwor

在我的一个应用程序中,我创建了一种队列列表,以便我的应用程序能够以正确的顺序发送midi信号

因此,每当我想播放midi音符时,我都会将该midi音符添加到列表中

我还有一个backgroundworker在运行,它会不断检查“队列”中是否有票据等待,如果有,他会将其发送到outputdevice

现在我想对它进行压力测试,20个测试中有19个工作得很好。偶尔,我会收到一个nullexception错误。事实是,我不知道为什么它会给我这个错误

我能想到的唯一一件事是,当backgroundworker检查队列中是否有便条在等待时,还有第二个参数仍然丢失,这就是他出错的原因

但是,当我查看队列的内容时,它们都在那里

那么,让我向您展示代码:

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);
                    }
                }
            }
        }
    }
上面写着:

对象引用未设置为对象的实例

但是,当我查看MIDI队列时,它包含以下值:

延迟:0

注:5

现在,我试图通过将错误放入try-catch块来绕过它,但我想知道是什么导致了这个问题

有人对此有想法吗


谢谢

如果这些操作是在不同的线程中完成的,那么在添加或删除项目时应该锁定MIDI队列

推送项目时:

lock (midiQueue) { midiQueue.Add(new queueClass(noteNumber, delay)); }
当您弹出项目时:

lock (midiQueue) { /* the pop operation(s) */
使用项目时:

lock (midiQueue)
{
   if (midiQueue != null && midiQueue.Count > 0)
   {
     if (midiQueue[0].note > -1 && midiQueue[0].delay > -1)
                    sendNote(midiQueue[0].note, midiQueue[0].delay);
   }
}

如果这些操作是在不同的线程中完成的,那么在添加或删除项目时应该锁定MIDI队列

推送项目时:

lock (midiQueue) { midiQueue.Add(new queueClass(noteNumber, delay)); }
当您弹出项目时:

lock (midiQueue) { /* the pop operation(s) */
使用项目时:

lock (midiQueue)
{
   if (midiQueue != null && midiQueue.Count > 0)
   {
     if (midiQueue[0].note > -1 && midiQueue[0].delay > -1)
                    sendNote(midiQueue[0].note, midiQueue[0].delay);
   }
}
您可以检查以下内容:

midiQueue != null && midiQueue.Count > 0
因此,您知道您有一个实例化的midiQueue,并且midiQueue中至少有一个元素

然后你要这样做:

midiQueue[0].note > -1 && midiQueue[0].delay > -1
这是你的问题。如果MIDI队列[0]为空,则MIDI队列[0]。注意:将引发“对象引用未设置为对象实例”异常

因此,您应该修改您的测试:

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);
   }
}
您可以检查以下内容:

midiQueue != null && midiQueue.Count > 0
因此,您知道您有一个实例化的midiQueue,并且midiQueue中至少有一个元素

然后你要这样做:

midiQueue[0].note > -1 && midiQueue[0].delay > -1
这是你的问题。如果MIDI队列[0]为空,则MIDI队列[0]。注意:将引发“对象引用未设置为对象实例”异常

因此,您应该修改您的测试:

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);
   }
}

midiQueue的值是什么?设置断点并单步执行代码时,是否已填充?
delay
note
属性是否已填充?如果
int
s为空,则不会出现错误。
int
s不能为空,其默认值为0。您正在使用非线程安全对象-
列表使用多线程。如果在使用midQueue的每个位置放置一个
,会发生什么?midQueue的值是什么?设置断点并单步执行代码时,是否已填充?
delay
note
属性是否已填充?如果
int
s为空,则不会出现错误。
int
s不能为空,其默认值为0。您正在使用非线程安全对象-
列表使用多线程。如果在您使用的每个位置周围放置一个
,会发生什么?我确实尝试过,并在添加或删除项目之前添加了锁。然而,这并不奏效。我仍然得到了例外。我更新了我的答案:在使用队列时,你也必须进行锁定。感谢Graffito的更新,但是我现在无法测试它,因为软件正在工作,我在星期二之前无法到达那里,但我会在那时候尝试并让你保持联系。我已经测试过,它仍然给我带来问题。然而,我不认为它与代码有关,但我认为它与Midi输出设备有关。因为当我使用内部Synth输出时,我没有任何问题。当我使用MidiSport输出时,它偶尔会使整个系统崩溃。我确实尝试过这样做,并在添加或删除项目之前添加了锁。然而,这并不奏效。我仍然得到了例外。我更新了我的答案:在使用队列时,你也必须进行锁定。感谢Graffito的更新,但是我现在无法测试它,因为软件正在工作,我在星期二之前无法到达那里,但我会在那时候尝试并让你保持联系。我已经测试过,它仍然给我带来问题。然而,我不认为它与代码有关,但我认为它与Midi输出设备有关。因为当我使用内部Synth输出时,我没有任何问题。当我使用MidiSport输出时,它偶尔会使整个系统崩溃。