Partilhar via


streamWriterBufferedDataLost MDA

Nota

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

O streamWriterBufferedDataLost assistente de depuração gerenciado (MDA) é ativado quando um StreamWriter é gravado, mas o Flush método or Close não é chamado subsequentemente antes que a StreamWriter instância do seja destruída. Quando esse MDA está habilitado, o tempo de execução determina se ainda existem dados armazenados em buffer no StreamWriter. Se existirem dados em buffer, o MDA será ativado. Chamar os métodos e WaitForPendingFinalizers pode forçar os Collect finalizadores a serem executados. Caso contrário, os finalizadores serão executados em momentos aparentemente arbitrários e, possivelmente, não serão executados na saída do processo. A execução explícita de finalizadores com este MDA ativado ajudará a reproduzir esse tipo de problema de forma mais confiável.

Sintomas

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

Motivo

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

O seguinte é um exemplo de código mal escrito que este MDA deve pegar.

// 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 acionada e, em seguida, 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 uma compilação de depuração. Isso ajudará a ativar de forma confiável o MDA, mas é claro que não corrige a causa do problema.

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

Resolução

Certifique-se de ligar Close ou Flush ligar para o StreamWriter antes de fechar um aplicativo ou qualquer bloco de código que tenha uma instância de um StreamWriter. Um dos melhores mecanismos para conseguir isso é criar a instância com um bloco C# using (Using no Visual Basic), 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 um StreamWriter estiver armazenado em uma variável estática e você não puder executar facilmente o código no final de sua vida útil), então chamar Flush o após seu StreamWriter último uso ou definir a AutoFlush propriedade para true antes de seu primeiro uso deve 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 tempo de execução

Este MDA não tem efeito sobre o tempo de execução.

Saída

Uma mensagem indicando que essa violação ocorreu.

Configuração

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

Consulte também