2016-09-28 104 views
0

我有下面的代码,它从覆盆子pi上的传感器读取温度。瞬态错误发生,deviceclient.sendmessage

代码是异步的,如果我只删除代码的最后一行,发送消息的那一行,我永远不会得到异常。 我的意思是这条线:

await deviceClient.SendEventAsync(message); 




private async void InitializeSensors() 
     { 
      string calibrationData; 
      //_periodicTimer.Dispose(); 
      // Inicializar el sensor bmp180 
      try 
      { 
       _bmp180 = new Bmp180Sensor(); 
       await _bmp180.InitializeAsync(); 
       calibrationData = _bmp180.CalibrationData.ToString(); //Retorna una cadena que representa al objeto actual. 
       if (_periodicTimer == null) 
       { 
        _periodicTimer = new Timer(this.TimerCallback, null, 0, readingInterval); 
       } 
      } 
      catch (Exception ex) 
      { 
       calibrationData = "Error de dispositivo! " + ex.Message; 
      } 

      var task = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
      { 
       //calibrationDataTextBlock.Text = ""; 
      }); 
     } 

     public async void TimerCallback(object state) 
     { 
      string temperatureText; 
      // Leer datos del sensor 
      try 
      { 
       var sensorData = await _bmp180.GetSensorDataAsync(Bmp180AccuracyMode.UltraHighResolution); 
       temperatureText = sensorData.Temperature.ToString(""); 
       //pressureText = sensorData.Pressure.ToString("F2"); 
       temperatureText += "°C"; 
       //pressureText += "hPa - " + BitConverter.ToString(sensorData.UncompestatedPressure); 
       var temperatureDataPoint = new 
       { 
        deviceKey = deviceKey, 
        deviceName = deviceName, 
        temperatura = sensorData.Temperature, 
        fecha = DateTime.Now 
       }; 
       var messageString = JsonConvert.SerializeObject(temperatureDataPoint); 
       var message = new Microsoft.Azure.Devices.Client.Message(Encoding.ASCII.GetBytes(messageString)); 
       message.Properties["Ambiente"] = ambiente; 

       ////temperatura.Text = temperatureText; 
       await deviceClient.SendEventAsync(message); 
      } 
      catch (Exception ex) 
      { 
       temperatureText = "Sensor Error: " + ex.Message; 
       //pressureText = "Sensor Error: " + ex.Message; 
      } 

      //// actualizaciones de la interfaz de usuario... deben ser invocados en el subproceso de interfaz de usuario 
      var task = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
      { 
       temperatura.Text = temperatureText; 
      }); 

     } 

如果我删除行,我可以看到,传感器工作,因为文本框与实际temmperature更新。

只有当我去掉了SendMessage函数线我得到的异常

我怎样才能解决这个问题?

+0

你得到了什么异常? – Jackie

+0

通用Windows应用程序未处理的类型为'System.ExecutionEngineException'的异常 – gina

回答

1

好吧,看起来像你有一些线程安全问题。

根据https://msdn.microsoft.com/en-us/library/microsoft.azure.devices.client.deviceclient.aspx,(DeviceClient的)任何实例成员不保证是线程安全的。

因此,当您使用像SendEventAsync这样的东西时,您(开发人员)有责任关心线程安全性。

在你的情况,当你揭开序幕计时器,该框架将创建工作线程每个蜱经过的时间,这可能是一个问题,尤其是当

await deviceClient.SendEventAsync(message); 

的延迟undeterministic,所以你可能结束几个工作线程进行相同的SendEventAsync调用。

一个快速和简单的解决方法是添加的AutoResetEvent解决此API调用(更衣室不AWAIT同意),类似下面,

autoResetEvent.WaitOne(); 
await deviceClient.SendEventAsync(eventMessage); 
autoResetEvent.Set(); 

不要让这个的AutoResetEvent全球化,所以,它的所有共享工作者线程。 PS:我看到你正试图从一些Bmp180传感器读取数据,你可能想让这些调用也是线程安全的。

让我知道它是否适合你。