在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#中使用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;
}
}
}