Przestań blokować WinForms, gdy trwają testy proxy
Zastąp synchroniczny Task.WaitAll w obsłudze zdarzenia UI oczekiwanymi, ograniczonymi partiami, a następnie aktualizuj kontrolki w wznowionym kontekście UI.
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.