Правильный способ объединить бесконечную задачу с объектомC#

Место общения программистов C#
Ответить
Anonymous
 Правильный способ объединить бесконечную задачу с объектом

Сообщение Anonymous »

Мне нужны отзывы и идеи на пути к хорошо написанному классу C#.
Предположим, что у вас есть датчик температуры, который можно прочитать через HTTP-запрос. Я хочу создать класс, в котором каждый экземпляр обновляет свою температуру раз в секунду, пока объект жив:

Код: Выделить всё

public class Sensor
{
public float Temperature { get; private set; }
private readonly string Uri;
public Sensor(string uri)
{
Uri = uri;
Task.Factory.StartNew(async () =>
{
while (true)
{
await UpdateTemperatureAsync();
await Task.Delay(1000);
}
}, TaskCreationOptions.LongRunning);
}

private async Task UpdateTemperatureAsync()
{
//just example code... not necessarily working
HttpClient client = new();
var response = await client.GetStringAsync(Uri);
Temperature = float.Parse(response);
}
}
Пока выглядит неплохо. Но что происходит, когда объект становится неиспользованным и его собирают в мусор? Будет ли задача продолжать выполняться? Что происходит, когда возникает исключение? Как будет вести себя этот класс, когда программа будет закрыта? Действительно ли это лучший способ выполнить эту задачу?
Больше интуитивно, чем знания, я подумал, что было бы неплохо добавить токен отмены, чтобы убедиться, что задача обновления корректно отменен:

Код: Выделить всё

public class Sensor2 : IDisposable
{
public float Temperature { get; private set; }
private readonly string Uri;
private readonly Task UpdateTask;
CancellationTokenSource cts = new();
public Sensor2(string uri)
{
Uri = uri;
UpdateTask = Task.Factory.StartNew(async () =>
{
try
{
while (cts.IsCancellationRequested == false)
{
await Task.Delay(1000, cts.Token);
await UpdateTemperatureAsync();
}
}
catch (TaskCanceledException)
{
//expected end of task
}
catch (Exception ex)
{
//unexpected. Just print and try again
Console.WriteLine(ex.Message);
}
}, TaskCreationOptions.LongRunning);
}

private async Task UpdateTemperatureAsync()
{
HttpClient client = new();
var response = await client.GetStringAsync(Uri, cts.Token);
Temperature = float.Parse(response);
}

public void Dispose()
{
//try to kill the update task
cts.Cancel();
UpdateTask.Wait();
UpdateTask.Dispose();
//ready to be disposed
}
}
Это очень много кода. Действительно ли это лучше, чем раньше? Это правильное использование IDisposable?

Подробнее здесь: https://stackoverflow.com/questions/793 ... ith-object
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»