我正在开发一个使用 XAML 的通用 Windows 平台应用程序,该应用程序在Windows 10 IoT Core
. 该应用程序驱动 I2C 总线上的温度传感器。传感器类是MLX90614Thermometer
. 传感器DispatcherTimer
每 100 毫秒(大约)使用一次读数并更新移动平均值。当移动平均值的值变化超过指定阈值时,传感器会引发ValueChanged
事件并在事件 args 中提供新值。
在我的 ViewModel 类中TemperatureSensorViewModel
,我订阅了传感器的ValueChanged
事件并使用它来更新名为Ambient
和Channel1
的绑定属性Channel2
。这些属性绑定到 XAML UI 中的文本块。这是事件处理程序:
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
...
<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):应用程序调用了为不同线程编组的接口。(来自 HRESULT 的异常:0x8001010E (RPC_E_WRONG_THREAD)) 在 System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs managedArgs) 在 System.ComponentModel.PropertyChangedEventHandler.Invoke(对象发送者,PropertyChangedEventArgs e) 在 GalaSoft.MvvmLight.ObservableObject.RaisePropertyChanged(String propertyName) 在 GalaSoft.MvvmLight.ViewModelBase.RaisePropertyChanged[T](String propertyName, T oldValue, T newValue, Boolean 广播) 在 GalaSoft.MvvmLight.ViewModelBase.Set[T](String propertyName, T& field, T newValue, Boolean broadcast) 在 TA.UWP.Devices.Samples.ViewModel.TemperatureSensorViewModel.set_Channel1(双值) 在 TA.UWP.Devices.Samples.ViewModel.TemperatureSensorViewModel.HandleSensorValueChanged(对象发送者,SensorValueChangedEventArgs e) 在 TA.UWP.Devices.MLX90614Thermometer.RaiseValueChanged(UInt32 通道,双值) 在 TA.UWP.Devices.MLX90614Thermometer.SampleAllChannels() 在 TA.UWP.Devices.MLX90614Thermometer.b__37_0() 在 System.Threading.Tasks.Task.InnerInvoke() 在 System.Threading.Tasks.Task.Execute() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 TA.UWP.Devices.MLX90614Thermometer.d__37.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 TA.UWP.Devices.MLX90614Thermometer.d__38.MoveNext()
笏?我不明白这里发生了什么。谁能看到问题可能是什么?