Compartilhar via


StreamWriterBufferedDataLost MDA

Observação

Este artigo é específico para .NET Framework. Ele não se aplica a implementações mais recentes do .NET, incluindo o .NET 6 e versões posteriores.

O streamWriterBufferedDataLost MDA (assistente de depuração gerenciada) é ativado quando um StreamWriter é gravado, mas o Flush método ou Close não é chamado posteriormente antes que a instância do StreamWriter seja destruída. Quando esse MDA está habilitado, o runtime determina se os dados armazenados em buffer ainda existem dentro do StreamWriter. Se os dados armazenados em buffer existirem, o MDA será ativado. Chamar e CollectWaitForPendingFinalizers métodos pode forçar a execução de finalizadores. De outra forma, os finalizadores serão executados em momentos aparentemente arbitrários e possivelmente não na saída do processo. Executar explicitamente os finalizadores com esse MDA habilitado ajudará a reproduzir de forma mais confiável esse tipo de problema.

Symptoms

Um StreamWriter não grava os últimos 1 a 4 KB de dados em um arquivo.

Motivo

Os StreamWriter dados de buffers são armazenados internamente, o que exige que o método ou Flush o Close método seja chamado para gravar os dados em buffer no armazenamento de dados subjacente. Se Close ou Flush não for chamado adequadamente, os dados armazenados em buffer na instância poderão não ser gravados conforme o StreamWriter esperado.

Veja a seguir um exemplo de código mal escrito que este MDA deve capturar.

// Poorly written code.
void Write()
{
    StreamWriter sw = new StreamWriter("file.txt");
    sw.WriteLine("Data");
    // Problem: forgot to close the StreamWriter.
}

O código anterior ativará esse MDA de forma mais confiável se uma coleta de lixo for disparada e suspensa até que os finalizadores tenham terminado. Para rastrear esse tipo de problema, você pode adicionar o código a seguir ao final do método anterior em um build de depuração. Isso ajudará a ativar de forma confiável o MDA, mas é claro que ele não corrige a causa do problema.

GC.Collect();
GC.WaitForPendingFinalizers();

Resolução

Certifique-se de chamar Close ou antes de StreamWriter fechar um aplicativo ou qualquer bloco de código que tenha uma instância de um StreamWriterFlush . Um dos melhores mecanismos para conseguir isso é criar a instância com um bloco C# using (Using no Visual Basic), o que garantirá que o Dispose método para o gravador seja invocado, resultando no fechamento correto da instância.

using(StreamWriter sw = new StreamWriter("file.txt"))
{
    sw.WriteLine("Data");
}

O código a seguir mostra a mesma solução, usando try/finally em vez de using.

StreamWriter sw;
try
{
    sw = new StreamWriter("file.txt"));
    sw.WriteLine("Data");
}
finally
{
    if (sw != null)
        sw.Close();
}

Se nenhuma dessas soluções puder ser usada (por exemplo, se uma StreamWriter for armazenada em uma variável estática e você não puder executar facilmente o código no final de seu tempo de vida), chamar Flush após seu StreamWriter último uso ou definir a AutoFlush propriedade antes true de seu primeiro uso deverá evitar esse problema.

private static StreamWriter log;
// static class constructor.
static WriteToFile()
{
    StreamWriter sw = new StreamWriter("log.txt");
    sw.AutoFlush = true;

    // Publish the StreamWriter for other threads.
    log = sw;
}

Efeito no Runtime

Esse MDA não tem nenhum efeito no runtime.

Saída

Uma mensagem indicando que essa violação ocorreu.

Configuração

<mdaConfig>
  <assistants>
    <streamWriterBufferedDataLost />
  </assistants>
</mdaConfig>

Consulte também