Il pulsante Annulla deve fermare l'esecuzione. Se ogni controllo proxy intercetta l'annullamento e ritorna normalmente, il ciclo esterno passa semplicemente al proxy successivo. Lo schermo sembra allora che Annulla non abbia fatto nulla.

In WinForms .NET moderno, mantenere un'unica sorgente come campo del form e lasciare che l'annullamento raggiunga il gestore dell'evento:

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 è l'elenco di URI proxy già analizzato dall'applicazione. Le righe dell'elenco di proxy gratuiti possono alimentare un controllo consentito di un obiettivo pubblico; conservare il protocollo e usare solo i tipi supportati da questo gestore. L'interfaccia attende ogni operazione, quindi il ciclo dei messaggi resta libero di ricevere il clic di annullamento.

Portare il token fino alla rete

Il singolo controllo deve accettare quel token. Un controllo HTTP abbreviato può apparire così:

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 e RecordResult appartengono al checker esistente. Mantenere un limite adeguato alla dimensione della risposta e un timeout per questo endpoint. Un checker di produzione può riutilizzare i client per route; il frammento mostra dove viaggia l'annullamento, non un progetto di pool di connessioni.

Se i proxy falliti devono essere registrati e saltati, intercettare gli errori di rete attesi attorno al singolo controllo. Lasciare che l'annullamento dell'esecuzione sfugga al gestore esterno. Per controlli paralleli, condividere il token dell'esecuzione con ogni worker e attenderne il completamento prima di abilitare un'altra esecuzione.

Articoli correlati