Важно отличать от «идеального» и «реального мира».В идеале, async
должно быть полностью.В идеале все операции ввода-вывода должны быть асинхронными и не использовать потоки пула потоков, а Task.Run
используется только для методов, связанных с процессором.В идеале async void
следует использовать только для обработчиков событий.
В реальном мире иногда приходится смешивать async
и синхронизировать из-за нехватки времени (или поддержки библиотеки).В реальном мире не все операции ввода-вывода имеют асинхронные API-интерфейсы, и даже блестящие новые типы, такие как HttpClient
, используют потоки пула потоков для работы со старым кодом разрешения DNS, который никто не хочет тратить на исправление.В реальном мире async void
иногда является более чистым подходом, чем простые продолжения, даже если он не используется для обработчиков событий.
В вашем случае я бы просто использовал Task.Run
и не беспокоился об этом.Основные проблемы с Task.Run
связаны с тем, что вы используете его в приложении ASP.NET или в библиотеке, где это может помешать другому использованию пула потоков.Поскольку вы работаете с приложением пользовательского интерфейса, использование Task.Run
для ввода-вывода не является «идеальным», но это идеальный вариант в качестве компромисса.