事件有时为空

时间:2015-10-08 04:00:26

标签: c# winforms events nlog

我有一个奇怪的间歇性问题,我似乎无法一致地重现。

我有一个名为NotifyTarget的自定义NLog目标,如下所示:

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

当应用程序进入此状态&#34;错误状态&#34;时,它会持续整个会话 - 关闭表单并再次尝试继续失败,但重新启动应用程序通常会将其重新置于&#34;良好的状态&#34;。

这种行为可能是什么原因?

1 个答案:

答案 0 :(得分:1)

你可能有一个流氓条件断点。

如果您有一个测试null的地方,但条件是

Notify = null

而不是

Notify == null

然后断点将Notify设置为null而不是评估其值。