Перестаньте блокировать 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; ожидание пакета не может заставить неограниченную сетевую операцию завершиться.