возможно ли иметь исключение System.NullReferenceException в этой строке?

#c# #.net

#c# #.net

Вопрос:

Мы поймали исключение (не знаю, почему во встроенной системе Win7 нет номера строки):

 Exception Message: System.NullReferenceException: Object reference not set to an instance of an object.
  

в этой строке, я думаю:

 ThreadPool.QueueUserWorkItem(HandleSaveStatus, (EvDoSaveStatus)systemSwEvent); 
  

Единственное место, о котором я могу думать, это (EvDoSaveStatus)systemSwEvent . Но я выполнил аналогичный тест следующим образом:

             SystemSwEvent ev = new EvDoSaveStatus();
            ev = null;
            EvDoSaveStatus evt = (EvDoSaveStatus)ev;
            string str = "Is it good?";
  

Исключение не генерируется. Это означает, что (EvDoSaveStatus)systemSwEvent все будет хорошо, даже systemSwEvent есть null каким-то образом.

Если один из членов EvDoSaveStatus стал нулевым, это не должно вызывать исключения в приведенном выше ThreadPool заявлении. Я прав?

РЕДАКТИРОВАТЬ: в этом случае:

     case "EvDoSaveStatus":
    {
 Log.logItem(LogType.DebugDevelopment, "EvDoSaveStatus", "dsm::publish()", "EvDoSaveStatus received");
 ThreadPool.QueueUserWorkItem(HandleSaveStatus, (EvDoSaveStatus)systemSwEvent);
  break;
   }
  

И у нас есть эта запись в журнале.

EDIT2: весь метод публикации:

 public void publish(SystemSwEvent systemSwEvent)
{
    try
    {
        switch (systemSwEvent.eventName)
        {
            case "EvLogin":
                {
                break;
                }
            case "EvLogoff":
                {
                break;
                }
            case "...":
                break;
            case "EvDoSaveStatus":
                {
                    Log.logItem(LogType.DebugDevelopment, "EvDoSaveStatus", "dsm::publish()", "EvDoSaveStatus received");
                    ThreadPool.QueueUserWorkItem(HandleSaveStatus, (EvDoSaveStatus)systemSwEvent);
                    break;
                }
        }
    }
    catch (Exception ex)
    {
        Log.logItem(LogType.Error, "Exception in publish()", "dsm::publish()", "Exception:"   ex   "nStackTrace:"   ex.StackTrace   "n"   ex.Message);
    }
}
  

Комментарии:

1. Вы абсолютно уверены, что виновата именно эта строка?

2. @Лассе: не на 100%, но на 99% уверен

3. @jfs: это все, что у нас есть: Исключение: System.NullReferenceException: ссылка на объект не установлена на экземпляр объекта. в XXX.XXX.DSMgr.dsm.publish(SystemSwEvent systemSwEvent) Трассировка стека: в XXX.XXX.DSMgr.dsm.publish(SystemSwEvent systemSwEvent) Ссылка на объект не установлена на экземпляр объекта.

4. Почему вы не предоставляете весь код для dsm::publish?

5. Это возможно, у вас есть одно. Там нет ничего, что позволило бы предположить, что он разбился в этом месте. Более вероятно, что объект systemSwEvent имеет значение null. Разверните .pdbs, чтобы получить номер строки.

Ответ №1:

 ev = null;
EvDoSaveStatus evt = (EvDoSaveStatus)ev;
  

приведет к evt нулевому значению. Вы можете передать null в качестве второго параметра QueueUserWorkItem , но обратный вызов, который вы ставите в очередь, должен обработать это.

HandleSaveStatus должно быть WaitCallback, поэтому оно принимает параметр объекта. Что он пытается сделать с этим объектом? Обрабатывает ли оно случай, когда оно равно null?

 public void HandleSaveStatus(object state){
    if (state == null)
    {
        return; // or whatever else you want to do with a null state
    }
    // Do work with non-null state
}
  

Комментарии:

1. если это произошло в методе HandleSaveStatus, исключение должно быть сгенерировано оттуда, что находится в другом месте.

2. OP говорит «Я думаю», что это находится в строке QueueUserWorkItem. Однако вы можете передать null в качестве параметра в этой строке, поэтому, если ThreadPool не равен null, «think» неверно. Рабочий элемент попадает в очередь и выдает ошибки при его выполнении. Давайте посмотрим на тело HandleSaveStatus и посмотрим, используется ли параметр без проверки на null.

3. Извините, вы оператор. Сегодня я чувствую себя не лучшим образом. В любом случае, вы говорите «я думаю», но без отслеживания стека было бы лучше подтвердить. Вставьте следующее в новое приложение WinForms, соберите и запустите его (не в режиме отладки). Вы получите аналогичный отчет о сбое. частная пустая форма 1_load(отправитель объекта, EventArgs e) { ThreadPool.QueueUserWorkItem(обрабатывает сохраненный статус, null); } общедоступная пустая форма обрабатывает сохраненный статус (состояние объекта) { MessageBox. Показать (состояние. toString()); }

Ответ №2:

Здесь дикие догадки…

Согласно документации для QueueUserWorkItem, оно выдаст исключение NullReferenceException только тогда, callback когда первый параметр равен null.

Является ли HandleSaveStatus на самом деле методом? Если это метод экземпляра, вы уверены, что не вызываете этот код из конструктора базового класса до инициализации объекта?

Попробуйте разделить строку на эту и посмотреть, все еще ли ошибка во второй строке:

 WaitCallback callback = new WaitCallback(HandleSaveStatus);  
ThreadPool.QueueUserWorkItem(callback, (EvDoSaveStatus)systemSwEvent);
  

Явный вызов конструктора ( new WaitCallback ) на самом деле более подробный, чем необходимо, но это показывает, что создание делегата является другим возможным источником исключений NullReferenceException.

Комментарии:

1. В этом случае HandleSaveStatus должен быть методом, иначе код даже не компилировался бы. Обратный вызов null возможен, если вы назначаете его во время выполнения, а компилятор не может выполнить это раннее обнаружение. Вставьте следующее в форму и попробуйте выполнить сборку, вы получите имя ‘HandleSaveStatus’, не существующее в текущем контексте private void Form1_Load(отправитель объекта, EventArgs e) { ThreadPool.QueueUserWorkItem(HandleSaveStatus, null); } public void HandleSaveStatus2(состояние объекта) { MessageBox. Показать (состояние. toString()); }

2. В любом случае проголосуйте за это, потому что это определенно могло бы помочь кому-то в будущем, кто занимается подобными вещами.

3. @druttka — Да, код в моем ответе требует, чтобы это HandleSaveStatus был метод, а не переменная делегата. Было бы неплохо точно знать, какое у него есть.