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

WinForm C# Timer异常:DataGridView持续刷新问题求助

问题:Timer触发DataGridView持续刷新不符合预期

实现逻辑概述

你通过Timer定期从SQL Server更新DataGridView,核心逻辑如下:

  1. 在Timer事件外定义两个字符串变量:
string pervCount = "0";
string newCount = "0";
  1. Timer事件内先统计表中InvoiceID的数量:
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT COUNT(InvoiceID) FROM InvoicesHeaderTable;", conn);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
    newCount = dr.GetValue(0).ToString();
}
conn.Close();
  1. 对比计数变化,若不同则更新DataGridView:
if (pervCount != newCount)
{
    conn.Open();
    SqlCommand cmd1 = new SqlCommand("select InvoiceID, CustomerName,TotalInvoicePrice from InvoicesHeaderTable where CompleteStatus=0", conn);
    SqlDataAdapter da = new SqlDataAdapter(cmd1);
    DataTable dt = new DataTable();
    da.Fill(dt);
    if (dt.Rows.Count > 0)
    {
        CashierDgv.DataSource = dt;
    }
    conn.Close();
    pervCount = newCount;
}

问题分析

按逻辑pervCount会被赋值为newCount,后续Timer触发时条件应不成立,但DataGridView持续刷新,可能的原因如下:

  1. 统计逻辑与刷新逻辑不匹配:
    你统计的是整个表的InvoiceID数量,但刷新的是CompleteStatus=0的行。当表中其他行(CompleteStatus≠0)发生插入/删除时,COUNT(InvoiceID)会变化,触发刷新,但实际需要显示的行可能并未改变,导致不必要的持续刷新。
  2. 字符串比较的潜在问题:
    直接用字符串对比计数,若数据库返回的数值格式存在差异(比如意外的空格、空字符),会导致pervCount != newCount始终成立。
  3. 资源未正确释放:
    未使用using语句管理数据库连接、命令等资源,可能导致连接泄漏或对象状态异常,间接引发逻辑错误。
  4. UI线程问题:
    若使用的是System.Timers.Timer,事件在后台线程触发,直接操作UI可能导致异常或刷新异常,表现为看似持续刷新的现象。

解决方案

1. 修正统计逻辑,匹配刷新范围

将统计语句改为只统计CompleteStatus=0的行,确保只有目标数据变化时才触发刷新:

// 统计部分修改为
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT COUNT(InvoiceID) FROM InvoicesHeaderTable WHERE CompleteStatus=0;", conn);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
    newCount = dr.GetValue(0).ToString();
}
conn.Close();

2. 使用数值对比替代字符串对比

避免字符串格式差异导致的误判:

// 在Timer事件内先转换为数值
int prevNum = int.Parse(pervCount);
int newNum = int.Parse(newCount);

if (prevNum != newNum)
{
    // 原有刷新逻辑
    pervCount = newNum.ToString();
}

3. 用using语句管理资源

确保数据库对象正确释放,避免潜在异常:

// 统计部分优化
using (SqlConnection conn = new SqlConnection(你的连接字符串))
{
    conn.Open();
    using (SqlCommand cmd = new SqlCommand("SELECT COUNT(InvoiceID) FROM InvoicesHeaderTable WHERE CompleteStatus=0;", conn))
    {
        newCount = cmd.ExecuteScalar().ToString();
    }
}

// 刷新部分优化
int prevNum = int.Parse(pervCount);
int newNum = int.Parse(newCount);
if (prevNum != newNum)
{
    using (SqlConnection conn = new SqlConnection(你的连接字符串))
    {
        using (SqlCommand cmd1 = new SqlCommand("select InvoiceID, CustomerName,TotalInvoicePrice from InvoicesHeaderTable where CompleteStatus=0", conn))
        {
            SqlDataAdapter da = new SqlDataAdapter(cmd1);
            DataTable dt = new DataTable();
            da.Fill(dt);
            if (dt.Rows.Count > 0)
            {
                // 确保在UI线程操作控件
                if (CashierDgv.InvokeRequired)
                {
                    CashierDgv.Invoke(new Action(() => CashierDgv.DataSource = dt));
                }
                else
                {
                    CashierDgv.DataSource = dt;
                }
            }
        }
    }
    pervCount = newNum.ToString();
}

4. 检查Timer类型和间隔

  • 若使用System.Timers.Timer,确保已设置SynchronizingObject为窗体,避免后台线程操作UI;或者直接使用System.Windows.Forms.Timer,其事件触发在主线程。
  • 避免Timer间隔过小,确保前一次刷新操作完成后再触发下一次。

内容的提问来源于stack exchange,提问作者محمد السروجي

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 03:42:12