取消整个 WinForms 代理检查运行
为 WinForms 代理检查运行保留一个取消源,通过 HTTP 工作传播取消,并停止继续推进列表。
“取消”按钮应当停止这次运行。如果每个代理检查都捕获取消并正常返回,外层循环只会继续检查下一个代理,界面看起来就像“取消”什么都没做。
在现代 .NET WinForms 中,把一个取消源保留为窗体字段,并让取消传到事件处理程序:
private CancellationTokenSource? activeRun;
private async void startButton_Click(object sender, EventArgs e)
{
if (activeRun is not null) return;
using var run = new CancellationTokenSource();
activeRun = run;
startButton.Enabled = false;
try
{
foreach (Uri proxy in configuredProxies)
{
run.Token.ThrowIfCancellationRequested();
await CheckProxyAsync(proxy, run.Token);
}
statusLabel.Text = "Finished";
}
catch (OperationCanceledException) when (run.IsCancellationRequested)
{
statusLabel.Text = "Stopped";
}
finally
{
activeRun = null;
startButton.Enabled = true;
}
}
private void cancelButton_Click(object sender, EventArgs e)
=> activeRun?.Cancel();configuredProxies 是应用已经解析好的代理 URI 列表。来自免费代理列表的候选行可以用于受允许的公共目标检查;保留协议,并且只使用此处理程序支持的类型。UI 会等待每个操作,因此消息循环仍可接收取消点击。
将令牌传到网络
单次检查必须接收该令牌。简化的 HTTP 检查大致如下:
private async Task CheckProxyAsync(Uri proxy, CancellationToken token)
{
using var handler = new HttpClientHandler
{
Proxy = new System.Net.WebProxy(proxy),
UseProxy = true
};
using var client = new HttpClient(handler);
using var response = await client.GetAsync(
probeUri, HttpCompletionOption.ResponseHeadersRead, token);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync(token);
RecordResult(proxy, body);
}probeUri 和 RecordResult 属于现有检查器。请为该端点保留合适的响应大小上限和超时。生产检查器可以按路由复用客户端;这段代码展示取消如何传递,而不是连接池设计。
如果失败代理需要记录并跳过,请在单次检查周围捕获预期的网络故障。让运行取消向外层处理程序传播。对于并行检查,请与每个工作线程共享运行令牌,并在启用另一次运行前等待它们完成。