在c#中释放内存资源的技巧

本文关键字:资源 内存 释放 | 更新日期: 2023-09-27 18:12:31

有人能给我一些与释放资源(内存资源)相关的提示吗?我只是一个学生,我正在为一个假设的小市场构建一个系统,在测试将新产品添加到购物车的选项时,我发现-使用任务管理器-有些东西占用了资源,因为每次我点击特定按钮后,程序在调试期间使用的内存都会增加一些字节。

我想知道我做错了什么,我还使用dispose来释放用于连接数据库的资源。请帮助我,你不需要为我写任何代码,只是告诉我我还应该发布什么。

我上面提到的按钮是它的事件所在的buttonAdicionar, buttonAdicionar_Click

如果你可以看一下,这里是pastebin中的代码:pastebin.com/CdJbJAqc

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
namespace Projeto_TCC
{
    public partial class FormCaixa : Form
    {
        #region Campos
        // const string CONNECTION_STRING = "server=localhost;uid=root;pwd=root;database=Projeto_TCC";
        private string mensagemDeSaida = "finalizar da aplicação";
        private int item = 0;
        private double totalVenda = 0.0;
        #endregion
        #region Método construtor
        public FormCaixa()
        {
            InitializeComponent();
        }
        #endregion
        #region Evento Click do ToolStrip Encerrar sessão
        private void encerrarSessãoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Yes;
            mensagemDeSaida = "encerrar esta sessão";
            this.Close();
        }
        #endregion
        #region Evento Click do ToolStrip Sair
        private void sairToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        #endregion
        #region Evento Click do ToolStrip Sobre
        private void sobreToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutBoxProjeto().ShowDialog(); // Isso é uma boa prática?
        }
        #endregion
        #region Evento FormClosing do FormCaixa
        private void FormCaixa_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("Deseja " + mensagemDeSaida + "?", "Caixa", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                e.Cancel = true;
            mensagemDeSaida = "finalizar da aplicação";
        }
        #endregion
        #region Evento Click do Button Adicionar
        private void buttonAdicionar_Click(object sender, EventArgs e)
        {
            // Prepara a conexão com o DB
            MySqlConnection con = new MySqlConnection(Properties.Settings.Default.ConnectionString);
            // Objetos utilizado para a realização de alguns processos
            MySqlDataAdapter da = new MySqlDataAdapter();
            DataTable dt = new DataTable();
            // Prepara o comando em SQL que retorná os dados sobre o item a ser adicionado à lista
            MySqlCommand cmd = new MySqlCommand("SELECT codigo, descricao, unidMedida, vlUnitario FROM tabEstoque WHERE codBar = @codBar;", con);
            cmd.Parameters.Add("@codBar", MySqlDbType.VarChar).Value = textBoxCodBarras.Text;
            try
            {
                // Abre a conexão e executa o comando em SQL
                con.Open();
                da.SelectCommand = cmd;
                da.SelectCommand.ExecuteNonQuery();
                da.Fill(dt);
                // Caso haja alguma linha no DataSet ds então existe um produto com o codigo de barra procurado no banco de dados
                if (dt.Rows.Count == 1)
                {
                    bool itemIgual = false;
                    int rowIndex = 0;
                    // Passa por todas as linhas da lista de compras para verificar se existe outro item igual
                    foreach (DataGridViewRow dgvListaRow in dataGridViewLista.Rows)
                    {
                        // Verifica se o produto da linha da lista de compra é o mesmo do código de barras
                        if (dgvListaRow.Cells[1].FormattedValue.ToString() == dt.Rows[0][0].ToString())
                        {
                            // Verifica se estão tentando vender uma certa quantidade de um produto que esteja acima da quantidade do mesmo no estoque
                            if (!this.VerificarSeExcede(Convert.ToInt32(dgvListaRow.Cells[1].FormattedValue), Convert.ToInt32(dgvListaRow.Cells[3].FormattedValue) + 1))
                            {
                                // Adiciona mais um na quantidade do item na lista de compra
                                dgvListaRow.Cells[3].Value = Convert.ToInt32(dgvListaRow.Cells[3].FormattedValue) + 1;
                                // Multiplica o VL. ITEM. pela nova quantidade e armazena o resultado em VL. ITEM
                                dgvListaRow.Cells[6].Value = String.Format("{0:f}",
                                    (Convert.ToDouble(dgvListaRow.Cells[3].Value) * Convert.ToDouble(dgvListaRow.Cells[5].Value)));
                                // Adiciona o valor do produto ao valor total da venda
                                totalVenda += Convert.ToDouble(dgvListaRow.Cells[5].Value);
                            }
                            else
                            {
                                MessageBox.Show("Ocorreu a tentativa de vender uma certa quantidade deste produto que excede a quantidade do mesmo no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                            itemIgual = true; // Evita que o if abaixo seja executado
                            break; // Sai do loop para econimizar tempo no processamento
                        }
                        rowIndex++;
                    }
                    // Caso o item não seja igual a nenhum outro na lista ele é adicionado à lista
                    if (!itemIgual)
                    {
                        // Verifica se estão tentando vender uma certa quantidade de um produto que esteja acima da quantidade do mesmo no estoque
                        if (!this.VerificarSeExcede(Convert.ToInt32(dt.Rows[0][0].ToString()), 1))
                        {
                            dataGridViewLista.Rows.Add(
                                ++item,                     // ITEM
                                dt.Rows[0][0],    // CÓDIGO
                                dt.Rows[0][1],    // DESCRIÇÃO
                                1,                          // QTD.
                                dt.Rows[0][2],    // UN.
                                dt.Rows[0][3],    // VL. UNIT.
                                dt.Rows[0][3]);   // VL. ITEM.
                            // Adiciona o valor do produto ao valor total da venda
                            totalVenda += Convert.ToDouble(dt.Rows[0][3].ToString());
                        }
                        else
                        {
                            MessageBox.Show("Ocorreu a tentativa de vender uma certa quantidade deste produto que excede a quantidade do mesmo no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                    // Atualiza a label que o exibe o total da venda
                    labelTotal.Text = String.Format("Total: {0:c}", totalVenda);
                }
                else // Mensagem exibida caso a cosulta nao retorne alguma coisa
                {
                    MessageBox.Show("Este item não consta no banco de dados.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (MySqlException ex)
            {
                MessageBox.Show("Ocorreu um erro durante a comunicação com o banco de dados.'n'n" + ex.Message, "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                con.Close(); // Fecha a conexão
                // Liberam os recursos/espaços ocupados na memória
                da.Dispose();
                dt.Dispose();
                cmd.Dispose();
            }
            //textBoxCodBarras.Clear();
            //textBoxCodBarras.Focus();
        }
        #endregion
        private bool VerificarSeExcede(int codProd, int quantItem)
        {
            MySqlConnection con = new MySqlConnection(Properties.Settings.Default.ConnectionString);
            MySqlCommand cmd = new MySqlCommand("SELECT codigo, quantidade FROM tabestoque WHERE codigo = @codProd", con);
            cmd.Parameters.Add("@codProd", MySqlDbType.Int32).Value = codProd;
            MySqlDataAdapter da = new MySqlDataAdapter(cmd);
            DataTable dt = new DataTable();
            con.Open();
            da.SelectCommand.ExecuteNonQuery();
            da.Fill(dt);
            int quantDB = Convert.ToInt32(dt.Rows[0][1]);
            con.Close();
            cmd.Dispose();
            da.Dispose();
            dt.Dispose();
            // Verifica se a quantidade do produto no banco de dados é >= que a quantidade do item na lista
            if (quantDB >= quantItem)
                return false;
            else
                return true;
        }
    }
}

谢谢。

在c#中释放内存资源的技巧

我最好的猜测是开始在c#中使用using标签

不是

myConnection = new connection(connectionString);
myConnection.open();
//do something with connection
myconnection.close();

你应该试试:

using (connection myConnection = new connection(connectionstring))
{
 //do something with myConnection
}

另外,让你的按钮不直接调用DB注入代码,而是使用Control类。

`private void buttonAdicionar_Click(object sender, EventArgs e)`
        {
            controlClass.DoSomethingNow()
        }

并在控制类中使用以下方法:

controlClass :class
{
  //make singleton?
    public void DoSomethingNow()
            {
              using (connection myConnection = new connection(connectionstring))
              { 
                //do something with myConnection 
              }
            }
 }

这样你就确切地知道什么时候使用了什么。您的IDE,如Visual Studio,可能会根据编译器的提示帮助您重新定位代码以获得更好的性能。

此外,作为一般提示,尝试阅读设计模式。这些模式并不局限于c#,所以很高兴以后知道/必须知道。

您没有做任何本质上的错误,作为一个快速测试,您可能希望在关闭/处置时更改顺序,将命令和连接留到最后。

da.Dispose();
dt.Dispose();
cmd.Dispose();
con.Close(); 

不确定这是否会解决你的问题,如果你适应使用()建议在其他地方,你会自动得到正确的顺序。

我注意到的另一件事是,你使用数据适配器和数据表,但他们并没有真正增加任何价值,这两个只是增加不必要的内存开销,尝试使用数据阅读器代替。using()和DataReader的例子:

private bool VerificarSeExcede(int codProd, int quantItem)
{
  using(var con = new MySqlConnection(Properties.Settings.Default.ConnectionString)) 
  {
    using(var cmd = new MySqlCommand("SELECT codigo, quantidade FROM tabestoque WHERE codigo = @codProd", con)) 
    {
      cmd.Parameters.Add("@codProd", MySqlDbType.Int32).Value = codProd;
      con.open();
      using(var reader = cmd.ExecuteReader()) 
      {
        if(reader == null) 
           return false;  
        reader.Read();
        var quantDB = reader.GetInt32(1);
        // Verifica se a quantidade do produto no banco de dados é >= que a quantidade do item na lista
        if (quantDB >= quantItem)
          return false;
        else
          return true;
    }
  }
}