Я предлагаю отделить получение данных от презентации. Таким образом, вы сможете перенести тяжелую работу по извлечению данных в фоновый поток, не беспокоясь о том, как вы будете одновременно обновлять элементы управления пользовательским интерфейсом. Вот как можно создать метод GetSensorData
, который извлекает данные в виде массива элементов ValueTuple<string, double>
, представляющих имя и значение каждого датчика:
private (string, double)[] GetSensorData()
{
var list = new List<(string, double)>();
Computer computer = new Computer();
computer.Open();
//...
foreach (IHardware hardware in computer.Hardware)
{
foreach (ISensor sensor in hardware.Sensors.Where(
x => x.SensorType == SensorType.Temperature))
{
list.Add(sensor.Name, double.Parse(sensor.Value.ToString()));
}
}
computer.Close();
return list.ToArray();
}
Тогда Вы можете использовать метод Task.Run
, чтобы переложить тяжелую работу по извлечению данных в фоновый поток (поток ThreadPool
). Этот метод возвращает Task
, который можно ожидать асинхронно, так что код под await
имеет доступные данные для работы.
private async Task UpdateSystemTempsAsync(bool updateGauge)
{
var data = await Task.Run(() => GetSensorData()); // Offload to thread-pool
// While awaiting the UI remains responsive
// After the await we are back in the UI thread
foreach (var (sensorName, sensorValue) in data)
{
if (updateGauge)
{
UserControls.TempGauge tempGauge =
((UserControls.TempGauge)gaugeContainer.Controls[sensorName]);
if (tempGauge != null)
{
tempGauge.gauge.Value = Math.Round(sensorValue, 0);
}
}
else
{
var tempGauge = new UserControls.TempGauge(sensorName);
gaugeContainer.Controls.Add(tempGauge);
}
}
}
Наконец, вам нужно сделать обработчики событий async
:
private async void MainForm_Load(object sender, EventArgs e)
{
try
{
await UpdateSystemTempsAsync(false);
timer.Enabled = true;
}
catch { }
}
private async void timer_Tick(object sender, EventArgs e)
{
timer.Enabled = false;
try
{
await UpdateSystemTempsAsync(true);
timer.Enabled = true;
}
catch { }
}