瞬态错误发生程序,deviceclient.sendmessage [英] Transient Error Occurer, deviceclient.sendmessage
问题描述
我有以下代码从树莓派上的传感器读取温度.
I have the following code which reads a temperature from a sensor on a raspberry pi.
该代码是异步的,如果我仅删除代码的最后一行,即发送消息的那一行,就永远不会得到异常. 我的意思是这一行:
The code is asynchronous, and if I remove ONLY the last line of the code, the one that sends the message, I never get the exception. I meant this line:
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;
});
}
如果删除这些行,则可以看到传感器正在工作,因为文本框已更新为真实的温度.
If I remove the lines, I can see that the sensor is working because the Textbox is updated with the real temmperature.
仅当我取消注释sendmessage行时,我才会收到异常
Only when I uncomment the sendmessage line I get the exception
我该如何解决?
推荐答案
好的,看来您有一些线程安全问题.
OK, looks like you have some thread-safety problem.
每个 https://msdn.microsoft .com/en-us/library/microsoft.azure.devices.client.deviceclient.aspx ,(DeviceClient的)任何实例成员均不能保证是线程安全的.
Per https://msdn.microsoft.com/en-us/library/microsoft.azure.devices.client.deviceclient.aspx, Any instance members (of DeviceClient) are not guaranteed to be thread safe.
因此,使用SendEventAsync之类的东西时,照顾线程安全是您(aka开发人员)的责任.
So it is your(aka the developer) responsibility to take care of the thread-safety when using things like SendEventAsync.
在您的情况下,当您启动计时器时,框架将在每次滴答滴答过去时创建工作线程,这可能是个问题,尤其是在延迟时间为
In your case, when you kick off a timer, the framework will create worker threads each time the ticks elapsed, this could be an issue especially when the latency of
await deviceClient.SendEventAsync(message);
不确定,因此您可能会结束几个工作线程,进行相同的SendEventAsync调用.
is undeterministic, so you might end up several working threads making the same SendEventAsync calls.
一种快速简单的解决方法是在此API调用周围添加一个AutoResetEvent(locker与await不同),如下所示,
A quick and simple fix is to add an AutoResetEvent around this API call(locker does not agree with await), something like below,
autoResetEvent.WaitOne();
await deviceClient.SendEventAsync(eventMessage);
autoResetEvent.Set();
请将此autoResetEvent设置为全局,以便由所有辅助线程共享.
Do make this autoResetEvent global so that it's shared by all the worker threads.
PS:我看到您正在尝试从某些Bmp180传感器读取数据,您可能还希望对这些调用进行线程安全.
PS: I see you're trying to read from the some Bmp180 sensor, you might want to make those calls thread-safe as well.
让我知道它是否对您有用.
Let me know if it works for you.
这篇关于瞬态错误发生程序,deviceclient.sendmessage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!