Task.WaitAll w procedurze obsługi kliknięcia WinForms blokuje okno, nawet gdy same testy korzystają z asynchronicznego HTTP. Wątek UI nie może przetwarzać komunikatów, a przechwycone kontynuacje mogą potrzebować tego samego zablokowanego wątku.

W .NET 6 lub nowszym zamiast tego poczekaj na ograniczoną partię:

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

To należy do istniejącego formularza z dostępnymi System.Linq i System.Threading.Tasks. CheckProxyAsync wykonuje ograniczone asynchroniczne wejście i wyjście i zwraca jeden wynik; nie manipuluje kontrolkami z wątku w tle. ShowResults i ShowCheckError to metody aplikacji.

Zwykła kontynuacja await wraca do kontekstu UI, w którym rozpoczęła się obsługa, więc ShowResults może aktualizować kontrolki. Kod jawnie uruchamiany w innym wątku musi przekazywać dostęp do kontrolek przez obsługiwany mechanizm WinForms.

Darmowa lista proxy może dostarczyć adresy wejściowe; przekazuj tylko protokoły implementowane przez CheckProxyAsync. Osiem to przykładowy budżet. Następna partia czeka na najwolniejszy test w bieżącej partii, wymieniając część przepustowości na ograniczone tworzenie zadań. Zachowaj terminy każdego testu i anulowanie w CheckProxyAsync; oczekiwanie na partię nie sprawi, że nieograniczona operacja sieciowa się zakończy.

Powiązane artykuły