峰峦@叠嶂 2025-08-21 09:07 采纳率: 98%
浏览 11
已结题

给采集软件增加个防网络抖动和友好提示的功能;

请教一下,我的C#代码,是从本地数据库采集数据后,保存到指定的数据表,为了操作方便,我加上进度条展示,在我本地运行正常,而我们分公司的本地访问,就会出现网络报错(如下图),他们的网络老化严重,刚刚修复正常了,ping服务器地址,在2-3MS之间,间或会更高一点,但软件在报错提示后,进展条就一直存在不消失,即使后台已完成数据采集,我希望给我的代码增加个网络防抖动的功能,及出现错误有更友好的提示,请问怎么修改;

img

img

 if (Compro == "追溯码关联关系")
 {
     // 进度提示框,20250815设定;
     var progressForm = new Form();
     progressForm.Text = "处理中";
     progressForm.Width = 300;
     progressForm.Height = 120;
     progressForm.StartPosition = FormStartPosition.CenterScreen;
     progressForm.FormBorderStyle = FormBorderStyle.FixedDialog;
     progressForm.ControlBox = false;

     var progressBar = new ProgressBar();
     progressBar.Dock = DockStyle.Top;
     progressBar.Height = 30;
     progressBar.Minimum = 0;
     progressBar.Maximum = 100;
     progressBar.Value = 0;

     var label = new Label();
     label.Dock = DockStyle.Fill;
     label.TextAlign = ContentAlignment.MiddleCenter;
     label.Text = "正在查询数据,请稍候...";

     progressForm.Controls.Add(label);
     progressForm.Controls.Add(progressBar);
     progressForm.Show();
     progressForm.Refresh();


     // 在后台线程中执行耗时操作
     await Task.Run(() =>
     {
         // 更新UI需要在主线程中执行
         progressForm.Invoke((MethodInvoker)delegate
         {
             label.Text = "正在查询数据...";
             progressBar.Value = 10;
             progressForm.Refresh();
         });

         string Sqldrugquery = @"SELECT ID, b.BATCH, Code, boxCode ,LevelNo, SuNum ----0702,增加了ID
                                 FROM(
                                 SELECT j.PrefixID as ID, b.BATCH AS BATCH, b.BATCH_ID AS BATCH_ID, p1.EPC AS Code, p1.EPC_L3 AS boxCode,
                                 d.S_NAME as LevelNo, 1 AS SuNum
                                 FROM TDD_BATCH b
                                 JOIN TDD_BATCH_BARCODE_1 p1 ON b.BATCH_ID = p1.BATCH_ID-- - 荷丹片36
                                 JOIN TDD_BATCH_BARCODE_1 p3 ON p1.EPC_L3 = p3.EPC
                                 JOIN ADM_DICT d ON d.DICT_ID = p3.PACK_LEVEL
                                 JOIN w_drugInfo w ON w.PRODUCT_ID = b.PRODUCT_ID
                                 JOIN Uploadata.dbo.w_JdrugUpload j on w.NDC = j.NDC and b.BATCH = j.batchNo1
                                 WHERE p1.PACK_LEVEL = 318001

                                 UNION ALL

                                 SELECT
                                 j.PrefixID as ID, b.BATCH AS BATCH, b.BATCH_ID AS BATCH_ID, p8.EPC AS Code, p8.EPC_L3 AS boxCode,
                                 d.S_NAME as LevelNo, 1 AS SuNum
                                 FROM TDD_BATCH b
                                 JOIN TDD_BATCH_BARCODE_8 p8 ON b.BATCH_ID = p8.BATCH_ID--银黄20
                                 JOIN TDD_BATCH_BARCODE_8 p3 ON p8.EPC_L3 = p3.EPC
                                 JOIN ADM_DICT d ON d.DICT_ID = p3.PACK_LEVEL
                                 JOIN w_drugInfo w ON w.PRODUCT_ID = b.PRODUCT_ID
                                 JOIN Uploadata.dbo.w_JdrugUpload j on w.NDC = j.NDC and b.BATCH = j.batchNo1
                                 WHERE p8.PACK_LEVEL = 318001

                                 UNION ALL

                                 SELECT j.PrefixID as ID, b.BATCH AS BATCH, b.BATCH_ID AS BATCH_ID, p9.EPC AS Code, p9.EPC_L3 AS boxCode, d.S_NAME as LevelNo, 1 AS SuNum
                                 FROM TDD_BATCH b
                                 JOIN TDD_BATCH_BARCODE_9 p9 ON b.BATCH_ID = p9.BATCH_ID-- - 荷丹胶囊48
                                 JOIN TDD_BATCH_BARCODE_9 p3 ON p9.EPC_L3 = p3.EPC
                                 JOIN ADM_DICT d ON d.DICT_ID = p3.PACK_LEVEL
                                 JOIN w_drugInfo w ON w.PRODUCT_ID = b.PRODUCT_ID
                                 JOIN Uploadata.dbo.w_JdrugUpload j on w.NDC = j.NDC and b.BATCH = j.batchNo1
                                 WHERE p9.PACK_LEVEL = 318001

                                 UNION ALL

                                 SELECT j.PrefixID as ID, b.BATCH AS BATCH, b.BATCH_ID AS BATCH_ID, p10.EPC AS Code, p10.EPC_L3 AS boxCode, d.S_NAME as LevelNo, 1 AS SuNum
                                 FROM TDD_BATCH b
                                 JOIN TDD_BATCH_BARCODE_10 p10 ON b.BATCH_ID = p10.BATCH_ID-- - 荷丹胶囊36
                                 JOIN TDD_BATCH_BARCODE_10 p3 ON p10.EPC_L3 = p3.EPC
                                 JOIN ADM_DICT d ON d.DICT_ID = p3.PACK_LEVEL
                                 JOIN w_drugInfo w ON w.PRODUCT_ID = b.PRODUCT_ID
                                 JOIN Uploadata.dbo.w_JdrugUpload j on w.NDC = j.NDC and b.BATCH = j.batchNo1
                                 WHERE p10.PACK_LEVEL = 318001

                                 UNION ALL

                                 SELECT j.PrefixID as ID, b.BATCH AS BATCH, b.BATCH_ID AS BATCH_ID, p16.EPC AS Code, p16.EPC_L3 AS boxCode, d.S_NAME as LevelNo, 1 AS SuNum
                                 FROM TDD_BATCH b
                                 JOIN TDD_BATCH_BARCODE_16 p16 ON b.BATCH_ID = p16.BATCH_ID-- - 新银黄16
                                 JOIN TDD_BATCH_BARCODE_16 p3 ON p16.EPC_L3 = p3.EPC
                                 JOIN ADM_DICT d ON d.DICT_ID = p3.PACK_LEVEL
                                 JOIN w_drugInfo w ON w.PRODUCT_ID = b.PRODUCT_ID
                                 JOIN Uploadata.dbo.w_JdrugUpload j on w.NDC = j.NDC and b.BATCH = j.batchNo1
                                 WHERE p16.PACK_LEVEL = 318001

                                 UNION ALL

                                 SELECT j.PrefixID as ID, b.BATCH AS BATCH, b.BATCH_ID AS BATCH_ID, p1016.EPC AS Code, p1016.EPC_L3 AS boxCode, d.S_NAME as LevelNo, 1 AS SuNum
                                 FROM TDD_BATCH b
                                 JOIN TDD_BATCH_BARCODE_1016 p1016 ON b.BATCH_ID = p1016.BATCH_ID-- - 银黄8袋
                                 JOIN TDD_BATCH_BARCODE_16 p3 ON p1016.EPC_L3 = p3.EPC
                                 JOIN ADM_DICT d ON d.DICT_ID = p3.PACK_LEVEL
                                 JOIN w_drugInfo w ON w.PRODUCT_ID = b.PRODUCT_ID
                                 JOIN Uploadata.dbo.w_JdrugUpload j on w.NDC = j.NDC and b.BATCH = j.batchNo1
                                 WHERE p1016.PACK_LEVEL = 318001

                                 ) AS sub
                                 JOIN TDD_BATCH b ON sub.BATCH_ID = b.BATCH_ID-- 类型完全匹配

                                 WHERE b.PRODUCE_DATE >= @startdate AND b.PRODUCE_DATE <= @enddate;";

         SqlCommand Cmd = new SqlCommand(Sqldrugquery, ConnKcinfo);
         Cmd.Parameters.AddWithValue("@startdate", startdate);
         Cmd.Parameters.AddWithValue("@enddate", enddate);

         SqlDataAdapter sda3 = new SqlDataAdapter(Cmd);
         dt.Rows.Clear();
         dt.Columns.Clear();
         dataGridView1.Columns.Clear();

         // 更新进度
         progressForm.Invoke((MethodInvoker)delegate
         {
             label.Text = "正在获取数据...";
             progressBar.Value = 30;
             progressForm.Refresh();
         });

         sda3.Fill(dt);

         // 更新进度
         progressForm.Invoke((MethodInvoker)delegate
         {
             label.Text = $"已获取 {dt.Rows.Count} 条记录,准备插入...";
             progressBar.Value = 50;
             progressForm.Refresh();
         });

         // 批量插入
         using (SqlConnection ConnMesInfo = new SqlConnection(Conn3))
         {
             ConnMesInfo.Open();
             using (SqlBulkCopy bulkCopy = new SqlBulkCopy(ConnMesInfo, SqlBulkCopyOptions.TableLock, null))
             {
                 bulkCopy.DestinationTableName = "w_JTcodeUpload";
                 bulkCopy.BatchSize = 5000;
                 bulkCopy.BulkCopyTimeout = 600;

                 // 显式映射列(跳过 id 字段)
                 bulkCopy.ColumnMappings.Add("ID", "batchNo");
                 bulkCopy.ColumnMappings.Add("boxCode", "TlevelCode");
                 bulkCopy.ColumnMappings.Add("Code", "FlevelCode");
                 bulkCopy.ColumnMappings.Add("LevelNo", "PackLevel");
                 bulkCopy.ColumnMappings.Add("SuNum", "SuNum");

                 // 更新进度
                 progressForm.Invoke((MethodInvoker)delegate
                 {
                     label.Text = "正在插入数据...";
                     progressBar.Value = 70;
                     progressForm.Refresh();
                 });

                 bulkCopy.WriteToServer(dt);

                 // 更新进度
                 progressForm.Invoke((MethodInvoker)delegate
                 {
                     label.Text = "正在验证数据...";
                     progressBar.Value = 90;
                     progressForm.Refresh();
                 });

                 // 数据一致性验证
                 int targetCount = 0;
                 using (SqlConnection connVerify = new SqlConnection(Conn1))
                 {
                     connVerify.Open();
                     using (SqlCommand cmdVerify = new SqlCommand("SELECT COUNT(*) FROM w_JTcodeUpload", connVerify))
                     {
                         cmdVerify.CommandTimeout = 60;  // 设置60秒超时
                         targetCount = (int)cmdVerify.ExecuteScalar();
                     }
                 }

                 //// 更新进度
                 //progressForm.Invoke((MethodInvoker)delegate
                 //{
                 //    progressBar.Value = 100;
                 //    progressForm.Refresh();
                 //});
             }
         }
     })
 ;

     // 关闭进度窗口
     progressForm.Close();

     // 显示完成消息
     MessageBox.Show($"数据批量插入成功!共插入 {dt.Rows.Count} 条记录",
                         "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

     dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
 }

  • 写回答

5条回答 默认 最新

  • 紫雾凌寒 新星创作者: 人工智能技术领域 2025-08-21 09:16
    关注

    让 “紫雾凌寒” 来帮你回答,本回答结合 DeepSeek

    如果还有问题,请评论或点击头像私信,如果有帮助到您, 请关注、采纳、点赞

    1. 关键点分析:
      - 问题核心在于在网络不稳定(老化严重)的环境下,采集数据并保存到指定数据表的操作出现网络报错。
      - 已经添加了进度条展示,但在分公司网络环境下仍有问题。
    2. 解决方案:
      - 防网络抖动
      • 使用重试机制。当出现网络报错时,设置一个重试次数和重试间隔时间。例如:
    int maxRetry = 3;
    int retryInterval = 2000; // 2秒
    for (int i = 0; i < maxRetry; i++)
    {
        try
        {
            // 采集数据并保存到指定数据表的操作
            // 假设这是一个方法SaveDataToTable
            SaveDataToTable();
            break;
        }
        catch (Exception ex)
        {
            if (i < maxRetry - 1)
            {
                System.Threading.Thread.Sleep(retryInterval);
            }
            else
            {
                // 处理最终的异常情况,比如记录日志等
                Console.WriteLine($"最终异常: {ex.Message}");
            }
        }
    }
    
    • 友好提示
      • 在界面上添加一个提示框来告知用户当前操作的状态。例如,在开始采集数据前显示“正在准备采集数据,请稍候…”,在采集过程中显示进度,出现网络问题时显示“网络出现问题,正在重试…”等。
      • 可以使用MessageBox或者自定义一个提示控件来实现。以MessageBox为例:
    MessageBox.Show("正在准备采集数据,请稍候...");
    // 采集数据操作
    MessageBox.Show($"已完成{progress}%的采集进度");
    // 网络报错时
    MessageBox.Show("网络出现问题,正在重试...");
    
    1. 多种解决方案的优缺点:
      - 重试机制
      • 优点:简单直接,能够在一定程度上解决网络抖动导致的操作失败问题。
      • 缺点:如果网络问题是由于服务器端故障等原因导致,重试可能无法解决根本问题,并且过多的重试可能会浪费时间。
      • 友好提示
      • 优点:能让用户清楚了解操作的状态,增强用户体验。
      • 缺点:如果提示过于频繁,可能会干扰用户,所以需要合理控制提示的时机和内容。
    2. 总结:
      通过添加重试机制可以应对网络抖动问题,在出现网络报错时尝试多次操作。同时,配合友好提示能让用户更好地了解操作过程。在实际应用中,需要根据具体的网络环境和业务需求,合理调整重试次数、重试间隔时间以及提示的内容和显示方式,以达到更好的效果。

    希望以上解答对您有所帮助。如果您有任何疑问,欢迎在评论区提出。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 9月5日
  • 已采纳回答 8月28日
  • 创建了问题 8月21日