C# Azure IoT Hub接收:如何将函数内while循环的data变量全局访问?
解决方案
1. 新增全局字符串变量
在Program类中,与values字典同级声明一个静态字符串变量,用于存储最新的原始遥测数据:
namespace CentralSystem { internal class Program { static readonly string connectionString = "IoT Hub Connection string here"; static readonly string iotHubD2cEndpoint = "messages/events"; static EventHubClient eventHubClient; public static Dictionary<string, string> values = new Dictionary<string, string>(); // 新增全局变量存储原始data字符串 public static string latestRawDeviceData = string.Empty; // 后续方法代码不变... } }
2. 在接收方法中赋值全局变量
在ReceiveMessagesFromDeviceAsync的while循环内,解析出data后直接赋值给全局变量:
private static async Task ReceiveMessagesFromDeviceAsync(string partition, CancellationToken ct) { var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow); while (true) { if (ct.IsCancellationRequested) break; EventData eventData = await eventHubReceiver.ReceiveAsync(); if (eventData == null) continue; string data = Encoding.UTF8.GetString(eventData.GetBytes()); // 将data赋值给全局变量 latestRawDeviceData = data; values = JsonConvert.DeserializeObject<Dictionary<string, string>>(data); foreach (var kv in values) { Console.WriteLine(kv.Key + " : " + kv.Value); } Console.WriteLine(); } }
之后你就可以通过Program.latestRawDeviceData在外部直接访问最新的原始遥测数据字符串。
3. 线程安全优化(必加)
由于异步方法可能存在多线程并发访问全局变量的情况,为避免数据错乱,需要给全局变量的读写操作加锁:
namespace CentralSystem { internal class Program { static readonly string connectionString = "IoT Hub Connection string here"; static readonly string iotHubD2cEndpoint = "messages/events"; static EventHubClient eventHubClient; // 新增锁对象 private static readonly object _dataLock = new object(); public static Dictionary<string, string> values = new Dictionary<string, string>(); public static string latestRawDeviceData = string.Empty; private static async Task ReceiveMessagesFromDeviceAsync(string partition, CancellationToken ct) { var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow); while (true) { if (ct.IsCancellationRequested) break; EventData eventData = await eventHubReceiver.ReceiveAsync(); if (eventData == null) continue; string data = Encoding.UTF8.GetString(eventData.GetBytes()); // 加锁保护全局变量赋值 lock(_dataLock) { latestRawDeviceData = data; values = JsonConvert.DeserializeObject<Dictionary<string, string>>(data); } // 输出部分可以不用锁,因为只是读取当前values的副本 foreach (var kv in values) { Console.WriteLine(kv.Key + " : " + kv.Value); } Console.WriteLine(); } } }
如果其他地方需要读取这两个全局变量,也需要用lock(_dataLock)包裹读取逻辑,确保数据一致性。
额外建议
- 不要直接替换
values字典的引用,可改为清空现有字典后添加新键值对,避免其他线程读取到未初始化的字典:lock(_dataLock) { latestRawDeviceData = data; var newValues = JsonConvert.DeserializeObject<Dictionary<string, string>>(data); values.Clear(); foreach(var kv in newValues) { values[kv.Key] = kv.Value; } } - 若需保留历史数据,可改用
ConcurrentQueue<string>存储所有收到的data字符串,实现线程安全的历史记录存储。
内容的提问来源于stack exchange,提问作者Ananta Wakde
相关产品推荐
相关产品推荐

