Graeme_Grant
Вот альтернативный метод, основанный на асинхронных вызовах с использованием Асинхронный...Ожидать[^].
Асинхронный...Await использует пул потоков для управления многозадачностью. Количество потоков, выполняемых одновременно, зависит от процессора и количества ядер. Если вы хотите изменить настройку по умолчанию, то в следующей документации будет объяснено, как это сделать: потоки ThreadPool.Метод SetMinThreads(Int32, Int32) (System.Продевать Нитку) | Майкрософт Документы[^]
То служба WebClient[^] класс DownloadStringTaskAsync[^] метод, который мы можем использовать. Мы можем принудительно запустить метод из потока пользовательского интерфейса, вызвав ConfigureAwait(false)[^].
Чтобы помочь нам визуализировать, как это работает, давайте обернем вызов в метод:
private static async Task<Tuple<string, string>> GetUrlAsync(Uri url)
{
Console.WriteLine("thisIsAsyncStart: "
+ Thread.CurrentThread.ManagedThreadId);
// make our call on another thread
var result = await new WebClient()
.DownloadStringTaskAsync(url).ConfigureAwait(false);
Console.WriteLine("thisIsAsyncEnd: " + Thread.CurrentThread.ManagedThreadId);
// return both the uri passed and the data returned
return new Tuple<string, string>(url.ToString(), result);
// we return to the UI thread when we exit this method
}
Далее, нам нужно несколько URI для вызова:
private static List<Uri> urls = new List<Uri>()
{
new Uri("https://www.codeproject.com", UriKind.Absolute),
new Uri("https://apple.com", UriKind.Absolute),
new Uri("https://xamarin.com", UriKind.Absolute),
new Uri("https://nokia.com", UriKind.Absolute),
new Uri("https://samsung.com", UriKind.Absolute),
new Uri("https://www.microsoft.com", UriKind.Absolute),
new Uri("https://www.codeproject.com", UriKind.Absolute),
new Uri("https://apple.com", UriKind.Absolute),
new Uri("https://xamarin.com", UriKind.Absolute),
new Uri("https://nokia.com", UriKind.Absolute),
new Uri("https://samsung.com", UriKind.Absolute),
new Uri("https://www.microsoft.com", UriKind.Absolute),
new Uri("https://www.codeproject.com", UriKind.Absolute),
new Uri("https://apple.com", UriKind.Absolute),
new Uri("https://xamarin.com", UriKind.Absolute),
new Uri("https://nokia.com", UriKind.Absolute),
new Uri("https://samsung.com", UriKind.Absolute),
new Uri("https://www.microsoft.com", UriKind.Absolute),
new Uri("https://www.codeproject.com", UriKind.Absolute),
new Uri("https://apple.com", UriKind.Absolute),
new Uri("https://xamarin.com", UriKind.Absolute),
new Uri("https://nokia.com", UriKind.Absolute),
new Uri("https://samsung.com", UriKind.Absolute),
new Uri("https://www.microsoft.com", UriKind.Absolute),
new Uri("https://www.codeproject.com", UriKind.Absolute),
new Uri("https://apple.com", UriKind.Absolute),
new Uri("https://xamarin.com", UriKind.Absolute),
new Uri("https://nokia.com", UriKind.Absolute),
new Uri("https://samsung.com", UriKind.Absolute),
new Uri("https://www.microsoft.com", UriKind.Absolute),
};
Теперь есть два способа, которые я продемонстрирую, управляя несколькими задачами одновременно.
1.
WhenAll[
^] -
Создает задачу, которая будет завершена, когда все объекты задачи в массиве будут завершеныprivate static async Task RunWhenAllAsync()
{
var tasks = new List<Task<Tuple<string, string>>>();
foreach (var url in urls)
{
tasks.Add(GetUrlAsync(url));
}
await Task.WhenAll(tasks.ToArray());
foreach (var task in tasks)
{
var result = task.Result;
Console.WriteLine($"id: {task.Id} | url {task.Result.Item1} > length: {task.Result.Item2.Length}");
}
}
Выход:
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncEnd: 13
thisIsAsyncEnd: 11
thisIsAsyncEnd: 13
thisIsAsyncEnd: 13
thisIsAsyncEnd: 11
thisIsAsyncEnd: 16
thisIsAsyncEnd: 11
thisIsAsyncEnd: 12
thisIsAsyncEnd: 16
thisIsAsyncEnd: 15
thisIsAsyncEnd: 12
thisIsAsyncEnd: 12
thisIsAsyncEnd: 13
thisIsAsyncEnd: 11
thisIsAsyncEnd: 16
thisIsAsyncEnd: 11
thisIsAsyncEnd: 11
thisIsAsyncEnd: 16
thisIsAsyncEnd: 14
thisIsAsyncEnd: 14
thisIsAsyncEnd: 13
thisIsAsyncEnd: 12
thisIsAsyncEnd: 15
thisIsAsyncEnd: 14
thisIsAsyncEnd: 12
thisIsAsyncEnd: 13
thisIsAsyncEnd: 14
thisIsAsyncEnd: 11
thisIsAsyncEnd: 15
thisIsAsyncEnd: 11
id: 1 | url https://www.codeproject.com/ > length: 96485
id: 3 | url https://apple.com/ > length: 53646
id: 5 | url https://xamarin.com/ > length: 149548
id: 7 | url https://nokia.com/ > length: 73246
id: 9 | url https://samsung.com/ > length: 106147
id: 11 | url https://www.microsoft.com/ > length: 1020
id: 13 | url https://www.codeproject.com/ > length: 96479
id: 15 | url https://apple.com/ > length: 53646
id: 17 | url https://xamarin.com/ > length: 149548
id: 19 | url https://nokia.com/ > length: 73246
id: 21 | url https://samsung.com/ > length: 106147
id: 23 | url https://www.microsoft.com/ > length: 1020
id: 25 | url https://www.codeproject.com/ > length: 96485
id: 27 | url https://apple.com/ > length: 53646
id: 29 | url https://xamarin.com/ > length: 149548
id: 31 | url https://nokia.com/ > length: 73246
id: 33 | url https://samsung.com/ > length: 106147
id: 35 | url https://www.microsoft.com/ > length: 1020
id: 37 | url https://www.codeproject.com/ > length: 96485
id: 39 | url https://apple.com/ > length: 53646
id: 41 | url https://xamarin.com/ > length: 149548
id: 43 | url https://nokia.com/ > length: 73246
id: 45 | url https://samsung.com/ > length: 106147
id: 47 | url https://www.microsoft.com/ > length: 1020
id: 49 | url https://www.codeproject.com/ > length: 96485
id: 51 | url https://apple.com/ > length: 53646
id: 53 | url https://xamarin.com/ > length: 149548
id: 55 | url https://nokia.com/ > length: 73246
id: 57 | url https://samsung.com/ > length: 106147
id: 59 | url https://www.microsoft.com/ > length: 1020
Выгоды:
- код очень прост
- поток пользовательского интерфейса не будет заблокирован
- задачи выполняются асинхронно в отдельных потоках пользовательского интерфейса
- результаты отображаются в том порядке, в котором были созданы задачи, а не в том порядке, в котором они были выполнены
Недостатки:
- выполнение будет ждать, пока все задачи не будут завершены
- пользователь не получит никакой обратной связи о прогрессе
2.
Member 10285969
сайт использует javascript, что является недостатком.
Richard Deeming
NB: Task.WhenAll
имеет перегрузку, которая занимает IEnumerable<Task>
так что в этом нет никакой необходимости. .ToArray()
вызов:
await Task.WhenAll(tasks);
Он также имеет перегрузку для задач с возвращаемым значением:
private static async Task RunWhenAllAsync()
{
IEnumerable<Tuple<string, string>> tasks = urls.Select(GetUrlAsync);
Tuple<string, string>[] results = await Task.WhenAll(tasks);
foreach (Tuple<string, string> result in results)
{
Console.WriteLine($"url {result.Item1} > length: {result.Item2.Length}");
}
}