Ngừng chặn WinForms khi các bước kiểm tra proxy đang chạy
Thay Task.WaitAll đồng bộ trong trình xử lý sự kiện UI bằng các lô có giới hạn và được chờ, sau đó cập nhật control trong UI context được tiếp tục.
Task.WaitAll trong trình xử lý nhấp của WinForms chặn cửa sổ ngay cả khi bản thân các bước kiểm tra dùng HTTP bất đồng bộ. Luồng UI không thể xử lý thông điệp, và các continuation được giữ lại có thể cần chính luồng đang bị chặn đó.
Với .NET 6 trở lên, thay vào đó hãy await một lô có giới hạn:
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;
}
}Điều này thuộc về một form hiện có với System.Linq và System.Threading.Tasks sẵn có. CheckProxyAsync thực hiện nhập và xuất bất đồng bộ có giới hạn và trả về một kết quả; nó không thao tác control từ luồng nền. ShowResults và ShowCheckError là các phương thức của ứng dụng.
Continuation thông thường của await quay về UI context nơi trình xử lý bắt đầu, nên ShowResults có thể cập nhật control. Mã chạy rõ ràng trên luồng khác phải chuyển quyền truy cập control qua cơ chế WinForms được hỗ trợ.
Danh sách proxy miễn phí có thể cung cấp địa chỉ đầu vào; chỉ truyền các giao thức được CheckProxyAsync triển khai. Tám là ngân sách ví dụ. Lô tiếp theo chờ bước kiểm tra chậm nhất trong lô hiện tại, đánh đổi một phần thông lượng để tạo tác vụ có giới hạn. Giữ thời hạn của từng bước kiểm tra và hủy bỏ trong CheckProxyAsync; await một lô không thể khiến một thao tác mạng không giới hạn hoàn tất.