- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 XAML 开发通用 Windows 平台应用程序,该应用程序在 Windows 10 IoT Core
下的 Raspberry Pi 上运行。该应用程序驱动 I2C 总线上的温度传感器。传感器类是 MLX90614Thermometer
。传感器使用 DispatcherTimer
每 100 毫秒(大约)读取一次读数并更新移动平均值。当移动平均值的值变化超过指定阈值时,传感器会引发 ValueChanged
事件并在事件参数中提供新值。
在我的 ViewModel 类 TemperatureSensorViewModel
中,我订阅了传感器的 ValueChanged
事件并使用它来更新名为 Ambient
的绑定(bind)属性,Channel1
和 Channel2
。这些属性绑定(bind)到 XAML UI 中的文本 block 。这是事件处理程序:
void HandleSensorValueChanged(object sender, SensorValueChangedEventArgs e)
{
switch (e.Channel)
{
case 0:
Ambient = e.Value;
break;
case 1:
Channel1 = e.Value;
break;
case 2:
Channel2 = e.Value;
break;
}
}
...这里是 Ambient
的示例数据绑定(bind)...
<TextBlock x:Name="Ambient" Grid.Row="1" Text="{Binding Path=Ambient}" Style="{StaticResource FieldValueStyle}" />
我正在使用 MVVM Light Toolkit ,所以我的属性是这样实现的(只显示了 Ambient
,但其他的除了名称之外都是相同的):
public double Ambient
{
get { return ambientTemperature; }
private set { Set(nameof(Ambient), ref ambientTemperature, value); }
}
MVVM Light Toolkit 提供了 Set()
方法,它会自动为正在设置的属性引发 PropertyChanged
通知。
如果我响应按钮按下从传感器读取单个样本,则此方法正常工作。不过,一旦我启用自动采样模式(基于计时器),它就会开始抛出 COMExceptions
。所以这一定是某种与计时器相关的线程问题。
现在,如果我理解正确的话,运行时应该自动将 PropertyChanged
通知编码到 UI 线程;从堆栈跟踪来看,情况确实如此。但是,我最终得到了 COMException
。呃。
System.Runtime.InteropServices.COMException (0x8001010E): The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)) at System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs managedArgs) at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e) at GalaSoft.MvvmLight.ObservableObject.RaisePropertyChanged(String propertyName) at GalaSoft.MvvmLight.ViewModelBase.RaisePropertyChanged[T](String propertyName, T oldValue, T newValue, Boolean broadcast) at GalaSoft.MvvmLight.ViewModelBase.Set[T](String propertyName, T& field, T newValue, Boolean broadcast) at TA.UWP.Devices.Samples.ViewModel.TemperatureSensorViewModel.set_Channel1(Double value) at TA.UWP.Devices.Samples.ViewModel.TemperatureSensorViewModel.HandleSensorValueChanged(Object sender, SensorValueChangedEventArgs e) at TA.UWP.Devices.MLX90614Thermometer.RaiseValueChanged(UInt32 channel, Double value) at TA.UWP.Devices.MLX90614Thermometer.SampleAllChannels() at TA.UWP.Devices.MLX90614Thermometer.b__37_0() at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.Execute()--- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at TA.UWP.Devices.MLX90614Thermometer.d__37.MoveNext()--- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at TA.UWP.Devices.MLX90614Thermometer.d__38.MoveNext()
什么?我不明白这里发生了什么。谁能看出可能是什么问题?
最佳答案
经过进一步研究,认为我可以回答我自己的问题......
看来我对自动编码到 UI 线程的 PropertyChanged 事件做了一个无效的假设。我在有关 WPF 的文章中的一些地方读到了这一点,但正如@Clemens 在评论中指出的那样,这不是我们正在谈论的 WPF,它是通用 Windows 平台,它是 Windows 运行时 (WinRT) 的衍生物。
然后我找到this question这与我有相似之处,特别是张贴者误以为他正在处理 WPF。接受的答案让我想到了另一个 question regarding the MVVM Light Toolkit's DispatcherHelper
class ,它可用于将任何代码编码到调度程序线程。
所以,看来我必须自己做线程编码(我真的很讨厌Windows编程的这方面,我希望微软能做出线程安全的UI技术!)。
所以我更新了我的属性以使用此模式:
public double Ambient
{
get { return ambientTemperature; }
private set
{
ambientTemperature = value;
DispatcherHelper.CheckBeginInvokeOnUI(() => RaisePropertyChanged());
}
}
这似乎按预期工作。
我想很多人都会陷入这个泥潭,所以我把这个答案留在这里,希望人们在需要的时候能够找到它。
关于xaml - 为什么从计时器引发 PropertyChanged 事件会导致 COMException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34443048/
创建面向.net 4.5.1的winform项目 安装包PropertyChanged.Fody [ImplementPropertyChanged] public class PersonFody
创建面向.net 4.5.1的winform项目 安装包PropertyChanged.Fody [ImplementPropertyChanged] public class PersonFody
有什么方法可以配置 fody 不检查设置为属性的值 - 我遇到值相同的情况并且我想要设置属性,因为我在未调用的属性 setter 中有额外的逻辑。 最佳答案 这显然是在最初问题之后的几年,但供将来引用
在 WPF 项目中,我有一个绑定(bind)到 ViewModel 集合的 ItemsControl。它的 ItemTemplate 包含绑定(bind)到对象集合属性的图像控件。我有一个计时器,它每
我正在为我们的应用程序实现观察者模式 - 目前正在使用 RX 框架。 我目前有一个看起来像这样的例子: Observable.FromEventPattern(Instance.Address, "P
我处于从外部来源获悉某个特定实体已在我当前数据上下文之外更改的情况。我能够找到实体并像这样调用刷新 MyDataContext.Refresh(RefreshMode.OverwriteCurrent
我有一个实现 PropertyChanged 的类。我做了类似的事情来订阅它: p.PropertyChanged += (s, a) => { switch ( a.PropertyNa
Here's一个工作示例: $(document).on("input propertychange", ".myClass", function () { $('#result').appe
在我的 ViewModel 中,我有一个属性,它是模型列表: private List _locations = null; public List Locations { get {
这个问题在这里已经有了答案: Implementing INotifyPropertyChanged - does a better way exist? (34 个回答) 2年前关闭。 当我绑定(b
我希望以一种优雅的方式更新我的 ListView 。 这是我的代码: ObservableCollection tracks = new ObservableCollection(); Track t
我有一个 Silverlight 应用程序,我在其中实现了 MVVM 模式。 在我的应用程序中有一个子窗口,上面有 ComboBox。我将组合框的 ItemsSource 和 SelectedItem
我一直在使用NotifyProperyWeaver,并且注意到它在使用PropertyChanged.Fody的Fody的最新版本中已过时。 我让NotifyProperyWeaver仅编织属性所具有
我目前正在尝试使用更改的 Fody 属性创建一个带有 MVVM 的 WPF 项目。 public static class Model { public
我正在尝试让我的属性更改事件处理程序正常工作,并且我已经使用调试器检查了正在调用 OnPropertyChanged 方法,但它并没有像我期望的那样调用该方法。 public class MainVi
我有以下类结构 class Top : NotifyPropertyChanged { private List innerList; public bool IsInnerTrue
我有以下方法: void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.Pro
我遇到这样一种情况,我有几个变量,它们的值相互依赖,如下所示: A 是 B 和 C 的函数B 是 A 和 C 的函数C是A和B的函数 任一值都可以在 UI 上更改。我正在做这样的计算和更改通知: pr
我在 WPF 中有一个可视化控件,它利用了依赖属性。这些属性由字段支持,这些字段是类,有时需要通知所有绑定(bind),当实际包含的类被修改时,属性值已更改。 简单地说: MyDepProp 是 My
我已经实现了自定义 TextBox: public class MyTextBox : TextBox { // ... } 我从 XAML 使用: 并且它绑定(bind)到我的 ViewM
我是一名优秀的程序员,十分优秀!