在我的应用程序中,我使用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元素,而不是它创建的线程,并且通过使用this中提到的扩展方法来解决这个问题,所以请回答。
我的问题是为什么会这样?我的假设是,事件是在与引发事件相同的线程上处理的,那么为什么直接处理SessionSwitch事件与在处理SessionSwitch事件时引发事件的方法有区别呢?SystemEvents和我的活动有什么不同?我对这个问题有正确的解决办法吗?有更简单的解决办法吗?
发布于 2014-06-10 22:10:21
从一些测试来看,错误似乎在于不工作的代码是SystemEventCollector对象的实例化。MS在它们的SessionEvents.***处理程序中执行所有必要的编组,这就是为什么第一个示例工作时没有问题。在不工作的代码中,SystemEventCollector没有在OnStartup函数中实例化(这是从UI线程调用的),但基本上是使用构造函数。当从SessionEvents进行编组时,它会转到错误的线程,从而导致问题。
除了我最初的解决方案,这个问题也可以通过在SystemEventCollector函数中实例化OnStartup来解决。
protected override void OnStartup(StartupEventArgs e)
{
_sysEventCollector = new SystemEventCollector();
_sysEventCollector.SessionEvent += OnSessionEvent;
}https://stackoverflow.com/questions/24106767
复制相似问题