Хорошо, поэтому я много читал и работаю над лучшими способами использования async methods
и task
и т. Д. Я полагаю, что (в основном) это понимаю, но я хочу проверить, чтобы убедиться.
Я начал делать async wrappers
для задач синхронизации, используя Task.Run()
, но недавно прочитал, что гораздо лучше просто иметь sync method
и позволить приложению определить, нужно ли его передавать в другой поток с помощью Task.Run()
сам, что имеет смысл.Тем не менее, я также читал, что исключение для этого естественно async functions
.Я не уверен, что полностью понимаю «естественно асинхронный», но в качестве базового понимания кажется, что методы платформы .NET, которые предлагают async methods
, являются naturally async
и WebClient.DownloadFile/DownlodFileAsync
- один из них.
Так что яу меня есть два метода, и если кто-то захочет высказать свое мнение, я хотел бы проверить свое понимание и убедиться, что это правильно.
Метод первый - перемещение некоторых файлов в локальной операционной системе и выглядит следующим образом (псевдокод):
Public static void MoveStagingToCache()
{
...do some file move, copy, delete operations...
}
Второй выглядит так (псевдокод):
Public static void DownloadToCache()
{
...do some analysis to get download locations...
using (var wc = new WebClient())
{
wc.DownloadFile(new Uri(content.Url), targetPath);
}
...do other stuff...
}
Итак, мое понимание таково.Первый метод должен быть оставлен как есть, поскольку ни один из методов файловой операции не имеет async versions
и, следовательно, вряд ли естественно async
.Вызывающий может определить, нужно ли просто вызывать MoveStagingToCache()
для запуска синхронизации или вызывать Task.Run(()=>MoveStagingToCache())
для передачи его в фоновый поток.
Однако во втором методе загрузка, естественно, async
(если я не понимаю), чтобы он мог создать синхронизацию и асинхронную версию.Чтобы сделать это, я НЕ должен просто обернуть метод синхронизации следующим образом:
Public static Task DownloadToCacheAsync()
{
return Task.Run(()=>DownloadToCache());
}
Вместо этого я должен сделать основной метод асинхронным следующим образом:
Public static async Task DownloadToCache()
{
...do some analysis to get download locations...
using (var wc = new WebClient())
{
await wc.DownloadFileTaskAsync(new Uri(content.Url), targetPath);
}
...do other stuff...
}
, и тогда я смогусоздайте версию синхронизации следующим образом:
Public static void DownloadToCache()
{
DownloadToCacheAsync().Wait();
}
Это позволяет использовать естественный асинхронный метод, а также предлагает перегрузку синхронизации для тех, кто в ней нуждается.
Это хорошее пониманиесистема или я что-то напутал?
Кроме того, есть ли разница в WebClient.DownloadFileAsync
и WebClient.DownloadFileTaskAsync
только в том, что задача возвращает задачу для обнаружения ошибок?
РЕДАКТИРОВАТЬ
Хорошо, поэтому после некоторого обсуждения в комментариях и ответах я понял, что должен добавить некоторые подробности о моей системе и предполагаемом использовании.Это внутри библиотеки, которая предназначена для запуска на рабочем столе, а не ASP.Таким образом, я не беспокоюсь о сохранении потоков для обработки запросов, основная задача состоит в том, чтобы держать поток пользовательского интерфейса открытым и отзывчивым для пользователя, а также передавать «фоновые» задачи в другой поток, который может обрабатываться системой, пока пользовательделает то, что им нужно.
Для MoveStagingToCache
это будет вызываться при запуске программы, но мне не нужно ждать завершения, чтобы продолжить загрузку или использование программы.В большинстве случаев она завершится до запуска и запуска остальной части программы и позволит пользователю сделать что-либо наиболее вероятное (максимум 5-10 секунд времени выполнения), но даже если оно не завершено до запуска взаимодействия с пользователем, программа будет работать нормально,Из-за этого мое основное желание здесь состоит в том, чтобы переместить эту операцию из потока пользовательского интерфейса, запустить ее и продолжить работу с программой.
Так что для этого мое текущее понимание состоит в том, что этот метод должен быть синхронизирован вбиблиотеки, но затем, когда я вызываю ее из основного потока (пользовательского интерфейса), я просто использую
Task.Run(()=>MoveStagingToCache());
Поскольку мне не нужно ничего делать по завершении, мне действительно не нужно ждать этогоправо?Если я просто сделаю выше, он начнет операцию в фоновом потоке?
Для DownloadToCache
, похоже, но немного по-другому. Я хочу, чтобы пользователь мог инициировать операцию загрузки, а затем продолжать работу в пользовательском интерфейсе до завершения загрузки. После его завершения мне нужно будет выполнить несколько простых операций, чтобы уведомить пользователя, что он готов пойти и включить кнопку «использовать» и т. Д. В этом случае я понимаю, что я бы создал это как асинхронный метод, который ожидает WebClient
скачать звонок. Это вытолкнет его из потока пользовательского интерфейса для фактической загрузки, но затем вернется после завершения загрузки, чтобы позволить мне делать все необходимые обновления пользовательского интерфейса после вызова await.
Правильно?