在进行 proxy 检查时不要阻塞 WinForms
用可等待的限量批次替换 UI 事件处理程序中的同步 Task.WaitAll,然后在恢复的 UI 上下文中更新控件。
在 WinForms 单击处理程序中使用 Task.WaitAll 会阻塞窗口,即使检查本身使用异步 HTTP 也是如此。UI 线程无法处理消息,而被捕获的后续代码可能仍需要那个被阻塞的线程。
对于 .NET 6 或更高版本,改为等待一个限量批次:
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;
}
}这适用于已存在且可用的 System.Linq 和 System.Threading.Tasks 的窗体。CheckProxyAsync 执行有界的异步输入输出并返回一个结果;它不会从后台线程操作控件。ShowResults 和 ShowCheckError 是应用程序方法。
await 的正常后续代码会回到处理程序启动时的 UI 上下文,因此 ShowResults 可以更新控件。显式在另一个线程上运行的代码必须通过 WinForms 支持的机制来编组控件访问。
免费 proxy 列表可以提供输入地址;只传入 CheckProxyAsync 实现的协议。八是示例预算。下一批要等待当前批次中最慢的检查,用部分吞吐量换取有界的任务创建。把每次检查的超时和取消保留在 CheckProxyAsync 中;等待批次并不能让无界的网络操作结束。