Ищем более приемлемый шаблон ожидания WebClient
для:
- Скачать файл (может занять пару сотен миллисекунд или несколько минут)
- Дождитесь завершения загрузки, прежде чем выполнять любую другую работу.
- Периодически проверять флаг другого класса (bool) и при необходимости отменять загрузку (невозможно изменить этот класс)
Ограничения:
- Невозможно использовать async/await, если это не что-то вроде
Task.Run(async () => await method())
- Когда вызывается метод
Download
, он просто должен вести себя как обычный метод, возвращающий строку - Может использовать любую функцию из .Net 4.5 и компилятора Roslyn.
- Не имеет значения, используется ли
WebClient.DownloadFileTaskAsync
илиDownloadFileAsync
; просто нужно иметь возможность отменить загрузку по мере необходимости с помощьюWebClient
Текущая реализация работает, но не совсем корректно. Есть ли более приемлемая альтернатива, чем использование цикла while
и Thread.Sleep
для периодической проверки otherObject.ShouldCancel
при использовании WebClient
?
private string Download(string url)
{
// setup work
string fileName = GenerateFileName();
// download file
using (var wc = new WebClient())
{
wc.DownloadFileCompleted += OnDownloadCompleted
Task task = wc.DownloadFileTaskAsync(url, fileName);
// Need to wait until either the download is completed
// or download is canceled before doing any other work
while (wc.IsBusy || task.Status == TaskStatus.WaitingForActivation)
{
if (otherObject.ShouldCancel)
{
wc.CancelAsync();
break;
}
Thread.Sleep(100);
}
void OnDownloadCompleted(object obj, AsyncCompletedEventArgs args)
{
if(args.Cancelled)
{
// misc work
return;
}
// misc work (different than other work below)
}
}
// Other work after downloading, regardless of cancellation.
// Could include in OnDownloadCompleted as long as this
// method blocked until all work was complete
return fileName;
}
Download
должен быть синхронным - ему все равно нечего делать во время ожидания завершения загрузки, так почему бы не опросить этот флаг тем временем. Конечно, вы можете добавить ко всему этому какие-то причудливые вещи, но это мало что изменит. - person Evk   schedule 28.02.2018otherObject.ShouldCancel
, чтобы сигнализироватьcancellationToken.Cancel()
? - person Metro Smurf   schedule 28.02.2018otherObject
(см. вопрос, 3-й пункт). - person Metro Smurf   schedule 28.02.2018ShouldCancel
. Теперь я склоняюсь к тому, чтобы оставить все как есть, если только не увижу какой-то другой убедительной альтернативы, которая может быть автономной в этом единственном методе. - person Metro Smurf   schedule 28.02.2018