2013-05-07 49 views
2

有人能給我一些與發佈資源(內存資源)相關的提示嗎?我只是一名學生,我正在爲一個假設的小型市場建立一個系統,在測試將新產品添加到購物車的選項時,我發現 - 使用任務管理器 - 某些東西擁有資源,因爲在每次單擊某個特定按鈕後,程序在調試過程中使用的內存在某些字節中會增加。在C#中釋放內存資源的提示

我想知道我在做什麼錯誤,我也使用了dispose來釋放用於連接數據庫的資源。請幫助我,你不必爲我編寫任何代碼,只是解釋我應該發佈什麼。

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

下面是代碼的引擎收錄,如果你可以看看: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; 
     } 
    } 
} 

感謝。

+0

乍看之下,這似乎並不那麼糟糕。 – 2013-05-07 12:42:07

+0

@DanielA。白色的問題是,假設這個系統一整天都在使用10Mb的內存,一天結束時可能使用500MB,這隻取決於銷售人員加入購物車的產品數量。 – Zignd 2013-05-07 12:45:14

+0

嘗試通過內存分析器運行它,看看哪些分配正在佔用這個空間。 – 2013-05-07 12:57:33

回答

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 
} 

同時,讓你的按鈕,以便其不直接調用數據庫注入代碼,而是使用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#,因此知道/必須稍後纔會很好。

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; 
    } 
    } 
}