Pergunta

DataSet e DataTable tanto implementar IDisposable, então, pelas melhores práticas convencionais, eu deveria chamar seus métodos Dispose ().

No entanto, pelo que eu li até agora, DataSet e DataTable realmente não tem nenhum recursos não gerenciados, assim Dispose () na verdade não faz muito.

Além disso, eu não posso simplesmente usar using(DataSet myDataSet...) porque DataSet tem uma coleção de tabelas de dados.

Assim, para ser seguro, eu precisaria para percorrer myDataSet.Tables, dispor de cada uma das tabelas de dados, em seguida, dispor do DataSet.

Assim, vale a pena o aborrecimento de chamar Dispose () em todos os meus DataSets e DataTables?

Adenda:

Para aqueles de vocês que pensam que DataSet devem ser eliminados: Em geral, o padrão para a eliminação é usar using ou try..finally, porque você quer garantia de que Dispose () será chamado.

No entanto, isso fica rápido muito feia para uma coleção. Por exemplo, o que você faria se uma das chamadas para Dispose () uma exceção? Você engoli-lo (o que é "mau") para que você possa continuar a dispor o próximo elemento?

Ou, você sugere que eu apenas chamar myDataSet.Dispose (), e esquecer a eliminação das tabelas de dados na myDataSet.Tables?

Foi útil?

Solução

Aqui estão algumas das discussões que explicam por que Descarte não é necessário para um DataSet.

de dispor ou não alienar ? :

O método Dispose no conjunto de dados só existe por causa do efeito colateral de inheritance-- em outras palavras, que na verdade não faz nada de útil na finalização.

deve descartar ser chamados DataTable e DataSet objetos inclui uma explicação de um MVP:?

O namespace system.data (ADONET) não contém recursos não gerenciados. Portanto, não há necessidade de dispor qualquer um desses como Contanto que você não adicionou-se algo especial para ele.

Compreender o método Dispose e conjuntos de dados tem uma com comentários da autoridade Scott Allen:

Em pratice raramente Descarte um DataSet porque oferece pouco benefício "

Assim, o consenso não é que não há atualmente nenhuma boa razão para chamar Dispose em um DataSet.

Outras dicas

Update (1 de dezembro de 2009):

Eu gostaria de alterar esta resposta e admitem que a resposta original era falho.

A análise original faz se aplica a objetos que exigem finalização - e o ponto de que as práticas não devem ser aceites na superfície sem um, em profundidade preciso compreender ainda stands.

No entanto, verifica-se que DataSets, DataViews, tabelas de dados finalização suprimir em seus construtores -. É por isso que chamar Dispose () sobre eles explicitamente não faz nada

Presumivelmente, isso acontece porque eles não têm recursos não gerenciados; Portanto, apesar do fato de que MarshalByValueComponent permite a definição de recursos não gerenciados, essas implementações particulares não têm a necessidade e pode, pois forgo finalização.

(que os autores .NET iria cuidar da finalização suprimir nos próprios tipos que normalmente ocupam mais memória fala sobre a importância desta prática, em geral, para os tipos de finalizable.)

Mas, para que esses detalhes ainda estão sob documentada desde o início do .NET Framework (quase 8 anos atrás) é bastante surpreendente (que você está essencialmente deixado a seus próprios dispositivos para peneirar embora conflitantes, material ambígua para colocar os pedaços juntos é frustrante às vezes, mas não fornece uma compreensão mais completa do quadro contamos com todos os dias).

Depois de muita leitura, aqui está o meu entendimento:

Se um objeto requer finalização, ele poderia ocupam memória por mais tempo do que ele precisa - aqui está o porquê: a) Qualquer tipo que define um destruidor (ou herda de um tipo que define um destruidor) é considerado finalizable; b) Na atribuição (antes de o construtor é executado), um ponteiro é colocado sobre a fila de finalização; c) Um objecto finalizable normalmente requer 2 colecções a ser recuperado (em vez do padrão 1); d) Suprimindo finalização não remover um objecto a partir da fila de finalização (como relatado por! FinalizeQueue em SOS) Este comando é enganosa; Saber o que os objetos estão na fila de finalização (em si) não é útil; Saber o que os objetos estão na fila de finalização e ainda exigem finalização seria útil (existe um comando para isso?)
Suprimir finalização transforma um pouco fora no cabeçalho do objeto que indica ao tempo de execução que não precisa ter o seu finalizador invocada (não precisa mover a fila FReachable); Ele permanece na fila de finalização (e continua a ser relatado por! FinalizeQueue em SOS)

As classes DataTable, DataSet, DataView são todos enraizado na MarshalByValueComponent, um objeto finalizable que pode (potencialmente) lidar com recursos não gerenciados

  • Porque DataTable, DataSet, DataView não apresentar recursos não gerenciados, eles suprimir finalização em seus construtores
  • Embora este seja um padrão incomum, ele libera o chamador de ter que se preocupar com a chamar Dispose após o uso
  • Isto, eo fato de que DataTables pode potencialmente ser compartilhados entre diferentes conjuntos de dados, é provável porque DataSets não se importam de dispor criança DataTables
  • Isto também significa que esses objetos vão aparecer sob a FinalizeQueue! No SOS
  • No entanto, esses objetos ainda deve ser recuperável após uma única coleção, como os seus homólogos não-finalizable

4 (novas referências):

Resposta Original:

Há um monte de enganar e respostas geralmente muito pobres sobre isso -. Qualquer um que desembarcou aqui deve ignorar o ruído e leia as referências abaixo com cuidado

Sem dúvida, Descarte deve ser chamado em qualquer objeto Finalizable.

DataTables está Finalizable.

Chamando Descarte significativamente acelera a recuperação de memória.

MarshalByValueComponent chamadas GC.SuppressFinalize (this) em seu Dispose () - pular isso significa ter que esperar por dezenas se não centenas de coleções Gen0 antes memória é recuperado:

Com esta compreensão básica de que a finalização já podemos deduzir alguns muito importante coisas:

Primeiro, objetos que precisam finalização vivem mais do que objetos que não. Na verdade, eles podem viver muito mais tempo. Por exemplo, suponha que um objeto que está em necessidades Gen2 para ser finalizado. A finalização será agendada, mas o objeto ainda está em gen2, por isso vai não ser re-recolhido até que o próximo coleção gen2 acontece. Isso poderia ser um tempo muito longo, de fato, e, de fato, se as coisas estão indo bem, será um longo tempo, porque coleções Gen2 são caros e, portanto, nós queremos que eles acontece muito raramente. Mais velho objetos que necessitam finalização poder tem que esperar por dezenas se não centenas de coleções Gen0 antes seu espaço é recuperado.

Em segundo lugar, objetos que precisam finalização causar danos colaterais. Desde o ponteiros de objeto internos devem permanecer válido, não só os objetos necessitando directamente finalização linger na memória, mas tudo o que o objeto refere-se a, directa e indirectamente, também permanecerá na memória. Se uma enorme árvore de objetos foi ancorado por um único objecto que necessário finalização, em seguida, toda a árvore iria demorar, potencialmente por um longo tempo como nós acabamos de discutir. Isto é por conseguinte, importante usar finalizadores com moderação e colocá-los em objetos que tem como objecto poucos interno ponteiros possível. Na árvore exemplo, eu apenas dei, você pode facilmente evitar o problema movendo o recursos que necessitam de finalização a um objeto separado e manter um referência a esse objecto na raiz da árvore. Com essa mudança modesta apenas o objeto (espero uma boa pequeno objecto) se prolongar e o custo finalização é minimizado.

Finalmente, os objetos que necessitam finalização criar trabalho para o segmento finalizador. Se o seu processo de finalização, é um um complexo, o primeiro e único segmento finalizador estará gastando muito tempo executar essas etapas, o que pode causar um acúmulo de trabalho e por conseguinte, causar mais objectos a ficar à espera de finalização. Portanto, é de vital importância que finalizadores fazer tão pouco trabalho quanto possível. Lembre-se também que, embora todos os ponteiros de objeto permanecem válidos Durante a finalização, que poderia ser o caso em que os ponteiros levar a objetos que já foram finalizado e pode, portanto, ser menos que útil. Em geral, é mais seguro para evitar seguintes ponteiros de objeto em código de finalização, embora o ponteiros são válidos. Um cofre, curta caminho de código de finalização é o melhor.

Leve-o de alguém que tenha visto 100s de MBs de tabelas de dados não referenciados em Gen2: este é extremamente importante e completely perdido pelas respostas sobre esta discussão.

Referências:

1 - http://msdn.microsoft.com/en-us/library/ms973837.aspx

2 - http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD ! 1104.entry http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage-collector-performance-using-finalizedispose-pattern.aspx

3 - http://codeidol.com/csharp/net- framework / Inside-the-CLR / Automatic-Memory-Management /

Você deve assumir que ele faz algo útil e chamar Dispose, mesmo que ele não faz nada na atual. encarnações NET Framework, não há nenhuma garantia de que vai ficar assim em versões futuras levando ao uso ineficiente de recursos.

Mesmo se o objeto não tem recursos não gerenciados, dispondo poderia ajudar GC quebrando gráficos de objeto. Em geral, se implementos objeto IDisposable então Dispose () deve ser chamado.

Se Dispose () realmente faz alguma coisa ou não depende de determinada classe. Em caso de DataSet, Descarte () aplicação é herdada de MarshalByValueComponent. Ele remove-se do recipiente e chama evento Disposed. O código fonte está abaixo (desmontado com .NET Reflector):

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        lock (this)
        {
            if ((this.site != null) && (this.site.Container != null))
            {
                this.site.Container.Remove(this);
            }
            if (this.events != null)
            {
                EventHandler handler = (EventHandler) this.events[EventDisposed];
                if (handler != null)
                {
                    handler(this, EventArgs.Empty);
                }
            }
        }
    }
}

Você cria as tabelas de dados a si mesmo? Porque iterar os filhos de qualquer objeto (como em DataSet.Tables) geralmente não é necessária, como é o trabalho do pai para descartar tudo que é membros filho.

Geralmente, a regra é: Se você criou e implementa IDisposable, Dispor. Se você não criá-lo, então não eliminá-lo, que é o trabalho do objeto pai. Mas cada objeto pode ter regras especiais, verifique a documentação.

Para .NET 3.5, que diz explicitamente "Dispor quando não estiver usando mais", de modo que é o que eu faria.

I chamar a qualquer momento dispor de um objeto implementa IDisposeable. Ele está lá por uma razão.

conjuntos de dados podem ser enormes porcos de memória. Quanto mais cedo eles podem ser marcados para a limpeza, o melhor.

update

Tem sido 5 anos desde que eu respondi a essa pergunta. Ainda de acordo com a minha resposta. Se houver um método dispose, ele deve ser chamado quando você é feito com o objeto. A interface IDispose foi implementado por uma razão.

Se a sua intenção ou o contexto desta questão é realmente a coleta de lixo, então você pode definir os conjuntos de dados e tabelas de dados para nulo explícita ou usar a palavra-chave usando e deixá-los ir fora do escopo. não Descarte não tanto quanto Tetraneutron disse mais cedo. GC irá recolher conjuntos de dados objetos que não são mais referenciados e também aqueles que estão fora do escopo.

Eu realmente gostaria que as pessoas SO forçados para baixo votação para realmente escrever um comentário antes downvoting a resposta.

Os conjuntos de dados implementar MarshalByValueComponent completa IDisposable, que implementa IDisposable. Desde conjuntos de dados são gerenciados não há nenhum benefício real para chamar Dispose.

Tente usar a função Clear (). Ele funciona muito bem para mim para a eliminação.

DataTable dt = GetDataSchema();
//populate dt, do whatever...
dt.Clear();

Não há necessidade de Dispose () porque DataSet herdar classe MarshalByValueComponent e MarshalByValueComponent implementar IDisposable interface

Primeiro de tudo eu iria verificar o que Descarte faz com um DataSet. Talvez usando o refletor de redgate vai ajudar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top