Отмена всего прогона проверки прокси в WinForms
Держите один источник отмены для прогона проверки прокси в WinForms, передавайте отмену в HTTP-работу и останавливайте продвижение списка.
Кнопка «Отмена» должна останавливать прогон. Если каждая проверка прокси перехватывает отмену и возвращается нормально, внешний цикл просто переходит к следующему прокси. Тогда экран выглядит так, будто отмена ничего не сделала.
В современном .NET WinForms держите один источник как поле формы и позвольте отмене дойти до обработчика событий:
private CancellationTokenSource? activeRun;
private async void startButton_Click(object sender, EventArgs e)
{
if (activeRun is not null) return;
using var run = new CancellationTokenSource();
activeRun = run;
startButton.Enabled = false;
try
{
foreach (Uri proxy in configuredProxies)
{
run.Token.ThrowIfCancellationRequested();
await CheckProxyAsync(proxy, run.Token);
}
statusLabel.Text = "Finished";
}
catch (OperationCanceledException) when (run.IsCancellationRequested)
{
statusLabel.Text = "Stopped";
}
finally
{
activeRun = null;
startButton.Enabled = true;
}
}
private void cancelButton_Click(object sender, EventArgs e)
=> activeRun?.Cancel();configuredProxies — это уже разобранный список URI прокси в приложении. Строки из списка бесплатных прокси могут питать разрешённую проверку публичной цели; сохраняйте протокол и используйте только типы, поддерживаемые этим обработчиком. Интерфейс ожидает каждую операцию, поэтому цикл сообщений остаётся свободным для получения нажатия отмены.
Передайте токен в сеть
Отдельная проверка должна принимать этот токен. Сокращённая HTTP-проверка может выглядеть так:
private async Task CheckProxyAsync(Uri proxy, CancellationToken token)
{
using var handler = new HttpClientHandler
{
Proxy = new System.Net.WebProxy(proxy),
UseProxy = true
};
using var client = new HttpClient(handler);
using var response = await client.GetAsync(
probeUri, HttpCompletionOption.ResponseHeadersRead, token);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync(token);
RecordResult(proxy, body);
}probeUri и RecordResult принадлежат существующему проверяющему. Держите подходящий предел размера ответа и тайм-аут для этой конечной точки. Производственный проверяющий может повторно использовать клиентов по маршруту; фрагмент показывает, куда идёт отмена, а не дизайн пула соединений.
Если неудачные прокси нужно записывать и пропускать, перехватывайте ожидаемые сетевые ошибки вокруг отдельной проверки. Позвольте отмене прогона выйти к внешнему обработчику. Для параллельных проверок делите токен прогона с каждым рабочим и ждите их завершения, прежде чем разрешить новый прогон.