У меня возникает странная периодическая проблема, которую я не могу воспроизвести последовательно.Событие иногда 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
действительно регистрируется:
Однако, если я поставил точку останова на if (Notify != null)
и осмотреть Notify
после продолжения выполнения и запуская журнал событий, по-видимому, был изменен на null
в какой-то момент:
Когда приложение входит в это «плохое состояние», оно сохраняется для всего сеанса - закрытие формы и повторная попытка продолжают работать, но перезапуск приложения обычно возвращает его в «хорошее состояние».
В чем может быть причина такого поведения?
Ваш метод 'ErrorConsole_FormClosing' отделяет журнал от события Notify, вы пытались поставить точку останова там, чтобы удостовериться, что его почему-то не вызывают больше, чем вы ожидаете? – DeanOC
Почему бы не переместить 'target.Notify + = Log;' в конструктор? – Julian