自定义事件与SystemEvent的区别

本文关键字:区别 SystemEvent 事件 自定义 | 更新日期: 2023-09-27 18:07:37

在我的应用程序中,我使用SystemEvents将对象添加到ObservableCollection(在本例中代码缩短)

public partial class App : Application
{
    private ObservableCollection<StateChanged> _messages = new ObservableCollection<StateChanged>();
    public ObservableCollection<StateChanged> messages { get { return _messages; } }
    protected override void OnStartup(StartupEventArgs e)
    {
        SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
    }
    private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
    {
        messages.Insert(0, new StateChanged(DateTime.Now, State.Logoff));
    }
}

以上代码运行正常

因为我不仅要处理SessionSwitch事件,还要处理SessionEnding等事件。我写了一个小类,应该为一些SystemEvents(再次缩短)引发一个"统一"事件

public class SystemEventArgs : EventArgs
{
    public State newState { get; set; }
}
public delegate void SystemEventHandler(object sender, SystemEventArgs e);
class SystemEventCollector
{
    public event SystemEventHandler SessionEvent;
    protected virtual void RaiseSystemEvent(SystemEventArgs e)
    {
        SystemEventHandler handler = this.SessionEvent;
        if (handler != null)
            handler(this, e);
    }
    public SystemEventCollector()
    {
        SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
    }
    protected void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
    {
        SystemEventArgs ea = new SystemEventArgs();
        ea.newState = State.Unknown;
        RaiseSystemEvent(ea);
    }
}

当我在应用程序中实例化这个类并订阅SessionEvent时,做同样的事情,像这样

public partial class App : Application
{
    private ObservableCollection<StateChanged> _messages = new ObservableCollection<StateChanged>();
    public ObservableCollection<StateChanged> messages { get { return _messages; } }
    private SystemEventCollector _sysEventCollector = new SystemEventCollector();
    protected override void OnStartup(StartupEventArgs e)
    {
         _sysEventCollector.SessionEvent += OnSessionEvent;
    }
    private void OnSessionEvent(object sender, SystemEventArgs e)
    {
        messages.Insert(0, new StateChanged(DateTime.Now, e.newState));
    }
}

messages.Insert()调用引发异常

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

我确实明白,我不能从另一个线程更新GUI元素,而不是在这个线程上创建的,并且通过使用这个SO答案中提到的扩展方法来解决这个问题。

我的问题是为什么会发生这种情况?我的假设是,事件是在同一个线程上处理的,因为它们被引发,那么为什么直接处理SessionSwitch事件和我在处理SessionSwitch事件时引发事件的方法之间存在差异?SystemEvents和我的活动有什么不同?我有解决问题的正确方法吗?有没有更简单的解决办法?

自定义事件与SystemEvent的区别

从一些测试看来,错误在于非工作代码是SystemEventCollector对象的实例化。MS在其SessionEvents.***处理程序中完成了所有必要的封送处理,这就是为什么第一个示例工作正常的原因。在非工作代码中,SystemEventCollector没有在OnStartup函数(从UI线程调用)中实例化,而是基本上使用构造函数实例化。当SessionEvents完成封送后,它会进入错误的线程,从而导致问题。

除了我原来的解决方案,这个问题还可以通过在OnStartup函数中实例化SystemEventCollector来解决。

protected override void OnStartup(StartupEventArgs e)
{
    _sysEventCollector = new SystemEventCollector();
     _sysEventCollector.SessionEvent += OnSessionEvent;
}