2015-10-08 2 views
0

У меня возникает странная периодическая проблема, которую я не могу воспроизвести последовательно.Событие иногда null

У меня есть пользовательский NLog цель под названием NotifyTarget, как показано ниже:

internal delegate void NotifyTargetEventArgs(string message); 

[Target("NotifyTarget")] 
internal class NotifyTarget : TargetWithLayout 
{ 
    public event NotifyTargetEventArgs Notify; 

    private List<string> _logs = new List<string>(); 

    public IList<string> Logs 
    { 
     get 
     { 
      return new ReadOnlyCollection<string>(_logs); 
     } 
    } 

    protected override void Write(LogEventInfo logEvent) 
    { 
     string message = Layout.Render(logEvent).TrimEnd(); 
     _logs.Add(message); 
     OnNotify(message); 
    } 

    protected void OnNotify(string message) 
    { 
     if (Notify != null) 
      Notify(message); 
    } 
} 

У меня есть приложение с формой ребенка называется ErrorConsole, который крепится к NotifyTarget.Notify:

public partial class ErrorConsole : Form 
{ 
    static NotifyTarget target; 

    static ErrorConsole() 
    { 
     target = LogManager.Configuration.FindTargetByName<NotifyTarget>("notify"); 
    } 

    public ErrorConsole() 
    { 
     InitializeComponent(); 
    } 

    private void ErrorConsole_Load(object sender, EventArgs e) 
    { 
     LoadLogs(); 
     target.Notify += Log; 
    } 

    private void LoadLogs() 
    { 
     errorBox.AppendText(string.Join(Environment.NewLine + Environment.NewLine, target.Logs)); 
     ScrollToLast(); 
    } 

    private void Log(string message) 
    { 
     errorBox.Invoke((MethodInvoker)(() => 
      { 
       string prefix = errorBox.Text == string.Empty ? "" : Environment.NewLine + Environment.NewLine; 
       errorBox.AppendText(prefix + message); 
       ScrollToLast(); 
      })); 
    } 

    private void ScrollToLast() 
    { 
     errorBox.ScrollToCaret(); 
    } 

    private void ErrorConsole_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     target.Notify -= Log; 
    } 
} 

ErrorConsole загружается из (назовем его MainForm) после нажатия на меню:

public partial class MainForm : Form 
{ 
    private ErrorConsole console; 

    // ... 

    private void errorConsoleMenu_Click(object sender, EventArgs e) 
    { 
     if (console == null || console.IsDisposed == true) 
     { 
      console = new ErrorConsole(); 
     } 

     console.Show(); 
    } 
} 

Всякий раз, когда я столкнулся с такой проблемой, я могу установить точку останова после target.Notify += Log; и проверить target.Notify с отладчиком, чтобы проверить, что метод Log действительно регистрируется:

Log is being registered to Notify

Однако, если я поставил точку останова на if (Notify != null) и осмотреть Notify после продолжения выполнения и запуская журнал событий, по-видимому, был изменен на null в какой-то момент:

enter image description here

Когда приложение входит в это «плохое состояние», оно сохраняется для всего сеанса - закрытие формы и повторная попытка продолжают работать, но перезапуск приложения обычно возвращает его в «хорошее состояние».

В чем может быть причина такого поведения?

+0

Ваш метод 'ErrorConsole_FormClosing' отделяет журнал от события Notify, вы пытались поставить точку останова там, чтобы удостовериться, что его почему-то не вызывают больше, чем вы ожидаете? – DeanOC

+0

Почему бы не переместить 'target.Notify + = Log;' в конструктор? – Julian

ответ

1

Возможно, у вас есть условная точка останова изгоев.

Если у вас есть один, где вы тестирования для нулевой, но условие

Notify = null

вместо

Notify == null

Тогда точка останова будет установка Notify к нулю, а чем оценка его ценности.

+0

На прошлой неделе я сильно укусил. – pm100

+0

@ pm100 Я думаю, что это случилось практически со всеми, кто использовал условные точки останова (включая меня). Я до сих пор не понимаю, как это позволяет IDE. – DeanOC

+0

Кажется, это не проблема, поскольку я даже никогда не использовал условные точки останова. –