none
Melhor Maneira de Destruir (Fechar) um Form? RRS feed

  • Pergunta

  • Seguinte, parece uma pergunta "básica", mas agora que andei tendo problemas sérios com isso...
    Eu sempre dava: this.close();
    Mas quando eu chamava a tela de novo, eu tava às vezes pegando Garbage (lixo) da mesma tela porém com dados anteriores...

    Qual a melhor maneira de destruir um Windows Form, por exemplo: destruir um FormProdutos?

    Quando eu chamo o FormProdutos, eu faço dessa maneira:

    // Declaração Global
    private FormProdutos fmProdutos = new FormProdutos();

    // Dentro do botão (exemplo dentro do FormPrincipal) pra chamar a tela FormProdutos:
    fmProdutos.ShowDialog();

    // Botão de Fechar do FormProdutos:
    Close();

    Isso que eu faço, mas quero saber o melhor jeito, pq desse jeito já não dá mais...
    Será que dou um dispose no botão de fechar de FormProdutos? Dou um fmProdutos = null; no FormPrincipal que chama a tela de produtos? qual o melhor jeito? quero destruir o form, para não pergar lixo nenhum...

    terça-feira, 7 de fevereiro de 2012 13:23

Respostas

  • José Wagner,

    Eu particularmente não gosto de usar declarações globais. 

    Eu costumo usar da seguinte maneira:

    using (form formulario = new form())
    {
        formulario.ShowDialog();
        //Outros comandos caso necessário.
    }

    o bloco "using" já executa o dispose automático quando vc sai dele.

    O que está acontecendo com o seu código é que quando você usa o this.Close(), ele fecha o form, mas fica aguardando o "Garbage colector" rodar para perceber que aquele form não está mais em uso e aí sim remover os dados da memória.

    Contudo, usando o bloco using na criação da instancia, você pode continuar usando o this.Close(), assim, enquanto você estiver dentro do bloco, você pode acessar "formulario.algumaCoisa" que os valores ainda estarão lá, mas ao sair do bloco using ele mata a instancia e nada mais estará acessível.


    Peterson Roberto Oliveira Seridonio
    Desenvolvedor C#
    MCTS Windows 7

    terça-feira, 7 de fevereiro de 2012 13:53
  • Sim, você pode usar o try-catch-finally dentro do bloco using para tratar alguma excessão que possa ocorrer dentro do seu form chamado, o try-catch será usado como um tratamento de erro, e não para forçar um dispose.

    E vc pode sim continuar usando o this.close como está hoje..


    Peterson Roberto Oliveira Seridonio
    Desenvolvedor C#
    MCTS Windows 7


    terça-feira, 7 de fevereiro de 2012 20:14

Todas as Respostas

  • Bom dia.

    Voce pode fazer assim:

    formulario.Dispose();

    http://msdn.microsoft.com/pt-br/library/system.idisposable.dispose.aspx

    Não é recomendado, mas voce pode em certos casos especificos, chamar explicitamente o Garbage Collector:

    http://msdn.microsoft.com/pt-br/library/system.gc%28v=vs.80%29.aspx

    http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx



    Consultoria .NET

    ANALISTA DESENVOLVEDOR
    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como resposta.


    terça-feira, 7 de fevereiro de 2012 13:34
  • Olá José

    a forma que vc esta fechando o form, não esta errada, quando vc usa o "This" isso seguinifica que vc esta fazendo uma referencia ao form atual

    portanto this.Close(), nao esta errado.

    Acredito que o problema esta na hora que vc abre o seu form.

    tente isolar suas rotinas, toda vez que vc precisar utilizar o form "frmProdutos", crie o objeto dentro da propria rotina, ou seja,  dentro do proprio botão vc cria o objeto frmProdutos.

    faça esse teste.

    espero ter ajuda, boa sorte ai amigão!!!


    Herbert Agles
    Se a resposta contribuiu com a sua necessidade, não se esqueça de marcá-la, assim você beneficiará outros usuários. Sua dúvida também pode ser as de outros!

    terça-feira, 7 de fevereiro de 2012 13:39
  • Certo, entendi, mas onde vou chamar o?

    formulario.Dispose();

    No botão Fechar de FormProdutos() ou no FormPrincipal logo abaixo de
    fmProdutos.ShowDialog();
    ou tanto faz?

    o Dispose() já contém o Close()?

    se for utilizar o Garbage Collector:
    GC.Collect();
    posso utilizar ele em qualquer trecho do código? e qual seria a hora mais interessante, num caso específico?

    terça-feira, 7 de fevereiro de 2012 13:41
  • José Wagner,

    Eu particularmente não gosto de usar declarações globais. 

    Eu costumo usar da seguinte maneira:

    using (form formulario = new form())
    {
        formulario.ShowDialog();
        //Outros comandos caso necessário.
    }

    o bloco "using" já executa o dispose automático quando vc sai dele.

    O que está acontecendo com o seu código é que quando você usa o this.Close(), ele fecha o form, mas fica aguardando o "Garbage colector" rodar para perceber que aquele form não está mais em uso e aí sim remover os dados da memória.

    Contudo, usando o bloco using na criação da instancia, você pode continuar usando o this.Close(), assim, enquanto você estiver dentro do bloco, você pode acessar "formulario.algumaCoisa" que os valores ainda estarão lá, mas ao sair do bloco using ele mata a instancia e nada mais estará acessível.


    Peterson Roberto Oliveira Seridonio
    Desenvolvedor C#
    MCTS Windows 7

    terça-feira, 7 de fevereiro de 2012 13:53
  • Interessante, entendi, então posso usar o using pra chamar o FormProdutos e dentro do FormProdutos() no botão fechar, posso continuar tendo o this.close(), certo?

    Usando o Using eu posso ausentar de usar Try e Finally para chamar o Form?

    terça-feira, 7 de fevereiro de 2012 18:03
  • Sim, você pode usar o try-catch-finally dentro do bloco using para tratar alguma excessão que possa ocorrer dentro do seu form chamado, o try-catch será usado como um tratamento de erro, e não para forçar um dispose.

    E vc pode sim continuar usando o this.close como está hoje..


    Peterson Roberto Oliveira Seridonio
    Desenvolvedor C#
    MCTS Windows 7


    terça-feira, 7 de fevereiro de 2012 20:14
  • Interessante, muito obrigado pela dica funcionou beleza.
    Mas continuando a trocar uma idéia.

    Será que não seria melhor deixar o form na declaração global:

    private form fm;

    e fazer o esquema que vc passou assim:

    using (fm = new form())
    {
        fm.ShowDialog();
        //Outros comandos caso necessário.
    }

    O que acha?

    e outra idéia:
    só usar o try e o finally sem o catch, compensa??? ou não faz sentido nenhum? eu usando o using já posso ir colocando tudo embaixo do fm.ShowDialog()? o que seria embaixo: atualizar uns campos, etc...

    quinta-feira, 9 de fevereiro de 2012 13:56
  • O try-finally vai executar os comandos até que chegue ao final do try ou que ocorra a primeira excessão.
    Este comando é recomandado caso seu código precise executar alguma rotina ao final da operação, independente de ter ocorrido um erro ou ter concluído a tarefa.

    O try-catch-finally é recomendado em operações onde você precisa fazer um tratamento específico caso tenha dado um erro na sua tarefa, e outro caso tenha concluído com sucesso.
    Um exemplo seria uma transação com o banco de dados.
    Pro exemplo:

    try
    {
        conexao.Open()   //Abrir conexão com o banco de dados.
        /*
            Executar comandos de inclusão, alteração e exclusão.
        */
        //Caso tenha concluído sem erro confirma as alterações.
        conexao.CommitTransaction() 
    }
    catch (Exception ex)
    {
        //Desfaz as alterações caso tenha dado erro.
        conexao.RollbackTransaction();
    }
    finally
    {
        conexao.Close();
    }


    Neste exemplo caso tenha concluído todos os comando eu confirmo a transação, caso tenha dado erro eu desfaço, mas em ambos os casos eu fecho a conexão com o banco de dados (finally).

    Quanto a usar uma declaração global ou local, vai de cada necessidade. Uma desvantagem de usar uma declaração global é que vários pontos do programa podem alterar os dados daquele objeto enquanto você está manipulando ele. Mas às vezes isso se torna uma necessidade, e neste caso a declaração global pode ser uma solução.

    Um exemplo de comandos que você poderia usar em baixo seria em uma busca, em uma tela onde você solicita informações ao usuário e depois le essas informações.

    public void SolictarEndereco()
    {
        using (frmSolicitarEndereco frmEndereco = new frmSolicitarEndereco())
        {
            frmEndereco.ShowDialog();
            cliente.Logradouro = frmEndereco.Logradouro;
            cliente.Numero = frmEndereco.Numero;
            cliente.Bairro = frmEndereco.Bairro;
            /*
            Ler outros campos do Form.
            */
        }
    }

    Neste estou solicitando que seja exibido um form com os dados de endereço para serem preenchidos, e após o preenchimento deles, leio os dados do form e preencho a minha classe.

    Uma desvantagem de uma declaração global neste caso seria a de que outro trecho do programa poderia alterar esses dados, sendo preenchidos com um dado e lido outro devido a alteração indevida.

    Espero ter ajudado.. Qualquer dúvida é só postar...


    Peterson Roberto Oliveira Seridonio
    Desenvolvedor C#
    MCTS Windows 7

    quinta-feira, 9 de fevereiro de 2012 17:24