You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#代理检测程序点击检查按钮卡顿,已尝试BackgroundWorker处理

解决BackgroundWorker代理检测时的程序卡顿问题

看起来你已经找对了方向——用BackgroundWorker把耗时的代理检测移到后台线程,但卡顿的问题大概率是因为你在DoWork事件里直接操作了UI控件(比如代码里的richTextBox)。后台线程不能直接访问UI线程所属的控件,这种跨线程操作会导致UI线程阻塞,出现你遇到的卡顿情况,甚至可能引发跨线程异常。

下面是修正后的完整方案:

1. 先配置BackgroundWorker的关键属性

在窗体初始化的时候,要开启进度报告支持(如果需要更新UI的话),同时绑定对应的事件:

public YourFormName()
{
    InitializeComponent();
    // 开启进度报告,这样才能调用ReportProgress
    backgroundWorker1.WorkerReportsProgress = true;
    // 可选:如果需要支持取消任务,开启这个属性
    backgroundWorker1.WorkerSupportsCancellation = true;
    
    // 绑定事件
    backgroundWorker1.DoWork += backgroundWorker1_DoWork;
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
    backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
}

2. 修改DoWork事件:只做后台检测,不碰UI

在后台线程里只执行代理检测的逻辑,把需要显示的结果通过ReportProgress传递给UI线程:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    WebProxy myproxy;
    for (int i = 0; i < Proxies.Count; i++)
    {
        string proxy = Proxies[i];
        // 检查是否有取消请求(可选)
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
        
        try
        {
            myproxy = new WebProxy(proxy);
            WebRequest request = WebRequest.Create("https://www.google.co.il/");
            request.Timeout = TimeOut;
            request.Proxy = myproxy;
            
            // 使用using确保资源及时释放,避免内存泄漏
            using (WebResponse re = request.GetResponse())
            {
                // 报告成功结果,第二个参数可以传递任意自定义数据
                backgroundWorker1.ReportProgress((i+1)*100/Proxies.Count, $"✅ 代理 {proxy} 测试成功");
            }
        }
        catch (Exception ex)
        {
            // 报告失败结果
            backgroundWorker1.ReportProgress((i+1)*100/Proxies.Count, $"❌ 代理 {proxy} 测试失败: {ex.Message}");
        }
    }
}

3. 在ProgressChanged事件里更新UI

这个事件是在UI线程执行的,所以可以安全地操作控件:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // 更新进度条(如果有添加进度条控件的话)
    progressBar1.Value = e.ProgressPercentage;
    
    // 更新richTextBox显示检测结果
    if (e.UserState != null)
    {
        richTextBox1.AppendText(e.UserState.ToString() + Environment.NewLine);
        // 自动滚动到最新内容
        richTextBox1.ScrollToCaret();
    }
}

4. 可选:处理任务完成后的逻辑

在RunWorkerCompleted事件里可以做任务结束后的提示,比如弹窗告知用户,或者重置控件状态:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        MessageBox.Show("代理检测已取消");
    }
    else if (e.Error != null)
    {
        MessageBox.Show($"检测过程中发生错误: {e.Error.Message}");
    }
    else
    {
        MessageBox.Show("所有代理检测完成!");
    }
    // 重置按钮状态(比如把"检查"按钮从禁用恢复为可用)
    btnCheck.Enabled = true;
}

关键注意点

  • 永远不要在DoWork事件里直接操作UI控件,所有UI更新都要通过ProgressChanged或者RunWorkerCompleted事件来完成。
  • 使用using语句包裹WebResponse这类实现了IDisposable的对象,确保网络资源及时释放。
  • 如果代理列表很大,记得添加取消功能,让用户可以中途终止检测,提升体验。

内容的提问来源于stack exchange,提问作者CodeLikeA l3oSS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:03:03