Я разрабатываю приложение для мониторинга определенных задач (например, если некоторые службы/веб-сайты в настоящее время работают и работают, некоторые записи в базе данных существуют и т. Д.). И поскольку большинство этих задач длится долго, я использую TPL
с async/await
.Замена для async void
У меня есть базовый класс для всех таких задач:
public abstract class LongRunningOperation
{
// .. some props...
internal async void Start()
{
try
{
this.Status = OperationStatus.Started;
await this.DoStart();
this.Status = OperationStatus.Finished;
}
catch (Exception e)
{
this.Status = OperationStatus.Error;
this.Message = e.ToString();
}
}
protected abstract Task DoStart();
}
И метод, который запускает эти задачи выглядят следующим образом:
public static LongRunningOperation[] LaunchOperations()
{
LongRunningOperation[] operations = GetAllLongRunningOperations();
foreach (var o in operations)
Task.Factory.StartNew(() => { o.Start(); });
return operations;
}
Массив, возвращаемый этот метод используется для мониторинга всех LongRunningOperation
s и запишите статистику. в настоящее время у меня есть консольное приложение, имеющее цикл while (true)
, который печатает статистику (имя, статус, текущее время выполнения) для каждой операции на экране (обновляя каждую секунду), пока все операции не будут завершены.
Вещь, которая меня беспокоит, это метод async void
. Я читал, что это плохая практика, чтобы использовать async void
методы, но:
- Я не могу понять, какой вред они могли бы сделать в моем сценарии
- Если изменить метод
Start
вернутьTask
, его возвращение значение никогда не будет использоваться в любом месте, и я не могу понять, почему мне нужно
Я был бы признателен, если кто-то может прояснить эти моменты
делать, если дубликат не знает, но может быть: http://stackoverflow.com/questions/12144077/async-wait-when-to-return-a-task-vs-void –
Единственное место, где имеет смысл использовать 'async void', - это когда вам нужно иметь дело с обработчиками событий в контексте синхронизации - контексты синхронизации делают его безопасным, а обработчики событий не должны возвращать значение. Используйте 'async Task' где-нибудь еще - нет причин не делать этого. Ваш код уже выглядит немного подозрительным - например, используя 'Task.Factory.StartNew' вместо' Task.Run' и используя его для запуска асинхронного метода. Почему бы не использовать задачу 'Start', чтобы отслеживать состояние долговременной операции вместо ваших собственных (вероятно, небезопасных) флагов? – Luaan
@ Luaan, я не возвращаю 'Task', потому что мне не нужен объект' Task' в вызывающем коде (я отслеживаю состояние операции usnig другими способами). И если я изменю его, чтобы вернуть «Задача» и сохранить вызов, поскольку он «o.Start()», я получаю предупреждение, предлагающее добавить 'await' к вызову, чего мне совсем не нужно. –