有关在C#中释放内存资源的提示

时间:2013-05-07 12:08:46

标签: c# performance resources

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

我想知道我做错了什么,我还使用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;
        }
    }
}

感谢。

2 个答案:

答案 0 :(得分:2)

我最好的猜测是开始使用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#,因此很高兴知道/必须在以后知道。

答案 1 :(得分:2)

你没有做任何本质上错误的事情,作为快速测试你可能想要在关闭/处理命令和连接时更改顺序。

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

不确定这会解决您的问题,如果您按照其他地方的建议调整使用(),您将自动获得正确的订单。

我注意到的另一件事是你使用DataAdapter和DataTable但它们并没有真正添加任何值,这两个只是增加了不必要的内存开销,请尝试使用DataReader。使用()和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;
    }
  }
}