为什么我的c#winforms程序在一天之后就陷入了困境?

3pvhb19x  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(291)

我有一个程序,每分钟更新两个datagridview对象,从我们的内部orders数据库中使用mysql查询,这样我们就可以跟踪旧的订单并确保它们得到处理。
它工作得很好,但如果你把程序放在它开始变得越来越慢,你真的注意到一天左右。重新启动程序修复了这个问题,但我真的很想知道为什么我不能让它继续运行。
以下是计时器代码及其调用的函数:

private void timer1_Tick(object sender, EventArgs e)
    {
        UpdateOrderDisplay();
    }

        private void UpdateOrderDisplay()
    {
        grdOrderItems.Rows.Clear();
        grdHoldOrders.Rows.Clear();
        string strsql;
        string CustomerName;
        string MyConString = "SERVER=**********;" + "DATABASE=***********;" + "UID=************;" + "PASSWORD=***********;";
        using (MySqlConnection connection = new MySqlConnection(MyConString))
        {
            MySqlCommand command = connection.CreateCommand();
            MySqlDataReader Reader;
            strsql = "select * from orders where ship_reference=0 and OnHold =0 order by order_id asc";
            command.CommandText = strsql;
            connection.Open(); Reader = command.ExecuteReader();
            while (Reader.Read())
            {
                if (Reader["payment_date"].ToString() != "")
                {
                    if (Reader["custom"].ToString().Contains("~*"))
                    {
                        CustomerName = Reader["custom"].ToString().Substring(0, Reader["custom"].ToString().IndexOf("~"));
                    }
                    else
                    {
                        CustomerName = Reader["shipping_address_name"].ToString();
                    }
                    grdOrderItems.Invoke(new MethodInvoker(() => grdOrderItems.Rows.Add(Convert.ToDateTime(Reader["payment_date"].ToString().Substring(0, 21)).ToString(), Reader["txn_id"].ToString(), CustomerName, Reader["mc_gross"].ToString(), Reader["memo"].ToString(), Reader["order_id"].ToString())));
                }
            }
            connection.Close();
            strsql = "select * from orders where OnHold =1 order by order_id asc";
            command.CommandText = strsql;
            connection.Open(); Reader = command.ExecuteReader();
            while (Reader.Read())
            {
                if (Reader["payment_date"].ToString() != "")
                {
                    if (Reader["custom"].ToString().Contains("~*"))
                    {
                        CustomerName = Reader["custom"].ToString().Substring(0, Reader["custom"].ToString().IndexOf("~"));
                    }
                    else
                    {
                        CustomerName = Reader["shipping_address_name"].ToString();
                    }
                    grdHoldOrders.Invoke(new MethodInvoker(() => grdHoldOrders.Rows.Add(Convert.ToDateTime(Reader["payment_date"].ToString().Substring(0, 21)).ToString(), Reader["txn_id"].ToString(), CustomerName, Reader["mc_gross"].ToString(), Reader["memo"].ToString(), Reader["order_id"].ToString(),Reader["Hold_Review_Date"].ToString().Substring(0,Reader["Hold_Review_Date"].ToString().IndexOf(" ")),Reader["payer_email"].ToString())));
                }
            }

            connection.Close();
        }

    }

另外,如果相关的话,这里有一些代码我用来对datagridview对象的行进行颜色编码,这样我们就可以很容易地分辨出哪个顺序更旧:

private void grdOrderItems_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
    {
        grdOrderItems.RowPrePaint += new System.Windows.Forms.DataGridViewRowPrePaintEventHandler(this.grdOrderItems1_RowPrePaint);

    }
    private void grdOrderItems1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
    {
        if (e.RowIndex <= grdOrderItems.Rows.Count - 1)
        {
            string StringNow = DateTime.Now.ToString();
            string NowTime = StringNow.Substring(StringNow.IndexOf(" ")+1, StringNow.Length- StringNow.IndexOf(" ")-1);
            string OrderDateTime = grdOrderItems.Rows[e.RowIndex].Cells[0].Value.ToString().Substring(0, grdOrderItems.Rows[e.RowIndex].Cells[0].Value.ToString().IndexOf(" ")+1) + NowTime;
            if ((Convert.ToDateTime(StringNow) - Convert.ToDateTime(OrderDateTime)).Days > 2)
            {
                grdOrderItems.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Tomato;
            }
            else
            {
                if ((Convert.ToDateTime(StringNow) - Convert.ToDateTime(OrderDateTime)).Days > 1)
                {
                    grdOrderItems.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Yellow;
                }
                else
                {
                    if ((Convert.ToDateTime(StringNow) - Convert.ToDateTime(OrderDateTime)).Days > 0)
                    {
                        grdOrderItems.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Tan;
                    }

                }
            }
        }
    }
rqenqsqc

rqenqsqc1#

你可能有一个mysqldatareader漏洞。当你做完每一件事 Reader 对象,处理它。这是实现这一目标的好方法;它对异常具有弹性 reader 变量在使用结束时超出范围。

using (var reader = command.ExecuteReader()
    {
        while (reader.Read())
        {
           /* your per-row logic here */
        }
    }

也可以使用close()执行此操作:

MySqlDataReader Reader; 
      ...
    Reader = command.ExecuteReader()
    while (Reader.Read())
    {
       /* your per-row logic here */
    }
    Reader.Close();

您正在关闭并重新打开每个查询的连接。那没必要。打开它一次,对两个查询都使用它,然后关闭它。
你可以考虑保持你的连接比一个计时器滴答响的时间更长(如果您有连接池,请忽略此建议。)
使用任务管理器查看程序占用多少cpu%和内存(早上和晚上)。如果内存在增长,就有某种漏洞。如果cpu%在增长,那么就需要进行某种列表处理,列表会随着每一个记号而变长。

pbwdgjma

pbwdgjma2#

我没有足够的信息来给出一个完整的答案,只是说这听起来像是一个大的对象堆问题,在这个问题上,您从数据库检索到的一个字段有时会超过85k loh阈值。
我能做的,甚至可能有帮助的,是向你展示如何极大地简化和改进预涂方法如下:

private void grdOrderItems1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
    if (e.RowIndex > grdOrderItems.Rows.Count - 1) return;
    var row = grdOrderItems.Rows[e.RowIndex];

    TimeSpan timeOfDay = DateTime.Now - DateTime.Today;
    //It *looks like* Cells[0].Value is already a DateTime, but I'm not 100% on this
    // If I'm wrong and it's a string, its worth it to parse just that one value to a DateTime here, and still plug that DateTime value into this code instead of the Cell.
    DateTime OrderDateTime = ((DateTime)row.Cells[0].Value).Date + timeOfDay;

    var days = (DateTime.Now - OrderDateTime).TotalDays;
    if (days > 2)
    {
        row.DefaultCellStyle.BackColor = Color.Tomato;
    }
    else if (days > 1)
    {
        row.DefaultCellStyle.BackColor = Color.Yellow;
    }
    else if (days > 0)
    {
        row.DefaultCellStyle.BackColor = Color.Tan;
    }
}

这减少了嵌套和额外的块,使它更容易理解,而且由于减少了字符串和日期时间值之间的来回,它的运行时间可能不到一半。文化/国际化问题使得在datetime和字符串之间的转换在任何方向上都是一个固有的缓慢且容易出错的操作。

相关问题