Task.WaitAll dans un gestionnaire de clic WinForms bloque la fenêtre même lorsque les vérifications elles-mêmes utilisent HTTP asynchrone. Le thread UI ne peut pas traiter les messages, et les continuations capturées peuvent avoir besoin de ce même thread bloqué.

Sous .NET 6 ou ultérieur, attendez plutôt un lot borné :

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;
    }
}

Cela s'inscrit dans un formulaire existant où System.Linq et System.Threading.Tasks sont disponibles. CheckProxyAsync effectue des E/S asynchrones bornées et renvoie un résultat ; elle ne manipule pas les contrôles depuis un thread d'arrière-plan. ShowResults et ShowCheckError sont des méthodes de l'application.

La continuation normale de await revient au contexte UI où le gestionnaire a commencé, si bien que ShowResults peut mettre à jour les contrôles. Le code exécuté explicitement sur un autre thread doit marshaller l'accès aux contrôles via le mécanisme WinForms pris en charge.

La liste de proxys gratuits peut fournir des adresses d'entrée ; ne transmettez que les protocoles implémentés par CheckProxyAsync. Huit est un budget d'exemple. Le lot suivant attend la vérification la plus lente du lot courant, échangeant une partie du débit contre une création de tâches bornée. Conservez les échéances de chaque vérification et l'annulation dans CheckProxyAsync ; attendre un lot ne peut pas faire aboutir une opération réseau non bornée.

Articles similaires