Перестаньте блокувати WinForms, поки виконуються перевірки proxy
Замініть синхронний Task.WaitAll в обробнику події UI на очікувані обмежені пакети, а потім оновлюйте елементи керування в відновленому контексті UI.
Task.WaitAll в обробнику клацання WinForms блокує вікно, навіть коли самі перевірки використовують асинхронний HTTP. Потік UI не може обробляти повідомлення, а захопленим продовженням може знадобитися той самий заблокований потік.
Для .NET 6 або новішої версії натомість очікуйте обмежений пакет:
private async void checkButton_Click(object sender, EventArgs e)
{
checkButton.Enabled = false;
try
{
var entries = proxyList.Lines
.Where(line => !string.IsNullOrWhiteSpace(line));
foreach (var batch in entries.Chunk(8))
{
var results = await Task.WhenAll(batch.Select(CheckProxyAsync));
ShowResults(results);
}
}
catch (Exception error)
{
ShowCheckError(error);
}
finally
{
checkButton.Enabled = true;
}
}Це належить до наявної форми з доступними System.Linq і System.Threading.Tasks. CheckProxyAsync виконує обмежений асинхронний ввід і вивід та повертає один результат; вона не керує елементами керування з фонового потоку. ShowResults і ShowCheckError — методи застосунку.
Звичайне продовження await повертається до контексту UI, де почався обробник, тож ShowResults може оновлювати елементи керування. Код, що явно виконується в іншому потоці, має передавати доступ до елементів керування через підтримуваний механізм WinForms.
Список безкоштовних proxy може надати вхідні адреси; передавайте лише протоколи, реалізовані в CheckProxyAsync. Вісім — це приклад бюджету. Наступний пакет чекає на найповільнішу перевірку в поточному пакеті, обмінюючи частину пропускної здатності на обмежене створення задач. Зберігайте терміни кожної перевірки та скасування в CheckProxyAsync; очікування пакета не може змусити необмежену мережеву операцію завершитися.