首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >定制事件与SystemEvent的区别

定制事件与SystemEvent的区别
EN

Stack Overflow用户
提问于 2014-06-08 13:44:36
回答 1查看 110关注 0票数 0

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

代码语言:javascript
复制
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引发一个“统一”事件(再次缩短)

代码语言:javascript
复制
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时,执行相同的操作,如下所示

代码语言:javascript
复制
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()调用引发异常

代码语言:javascript
复制
This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

我确实理解,我不能从另一个线程更新GUI元素,而不是它创建的线程,并且通过使用this中提到的扩展方法来解决这个问题,所以请回答。

我的问题是为什么会这样?我的假设是,事件是在与引发事件相同的线程上处理的,那么为什么直接处理SessionSwitch事件与在处理SessionSwitch事件时引发事件的方法有区别呢?SystemEvents和我的活动有什么不同?我对这个问题有正确的解决办法吗?有更简单的解决办法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-10 22:10:21

从一些测试来看,错误似乎在于不工作的代码是SystemEventCollector对象的实例化。MS在它们的SessionEvents.***处理程序中执行所有必要的编组,这就是为什么第一个示例工作时没有问题。在不工作的代码中,SystemEventCollector没有在OnStartup函数中实例化(这是从UI线程调用的),但基本上是使用构造函数。当从SessionEvents进行编组时,它会转到错误的线程,从而导致问题。

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

代码语言:javascript
复制
protected override void OnStartup(StartupEventArgs e)
{
    _sysEventCollector = new SystemEventCollector();
     _sysEventCollector.SessionEvent += OnSessionEvent;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24106767

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档