Partilhar via


streamWriterBufferedDataLost MDA

Observação

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 gerido (MDA) é ativado quando a StreamWriter é escrito em, mas o Flush método ou Close não é posteriormente chamado antes de a instância de ser StreamWriter destruída. Quando este MDA está ativado, o tempo de execução determina se ainda existem dados em buffer dentro do StreamWriterarquivo . Se existirem dados em buffer, o MDA é ativado. Chamar os Collect métodos e WaitForPendingFinalizers pode forçar os finalizadores a executar. De resto, os finalizadores funcionam em horários aparentemente arbitrários e, possivelmente, nem sequer ao sair do processo. Executar finalizadores explicitamente com este MDA ativado ajudará a reproduzir este tipo de problema de forma mais fiável.

Sintomas

A StreamWriter não escreve os últimos 1–4 KB de dados num ficheiro.

Motivo

O StreamWriter buffer os dados internamente, o que exige que o Close método ou Flush seja chamado para escrever os dados armazenados no armazenamento subjacente. Se Close for ou Flush não for chamado corretamente, os dados armazenados na StreamWriter instância podem não ser escritos como esperado.

Segue-se um exemplo de código mal escrito que este MDA deve detetar.

// 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á esta MDA de forma mais fiável se uma recolha de lixo for acionada e depois suspensa até que os finalizadores terminem. Para identificar este tipo de problema, pode adicionar o seguinte código ao final do método anterior numa compilação de depuração. Isto ajuda a ativar o MDA de forma fiável, mas claro que não resolve a causa do problema.

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

Resolução

Certifique-se de que liga Close ou Flush no StreamWriter antes de fechar uma aplicação ou qualquer bloco de código que tenha uma instância de StreamWriterum . Um dos melhores mecanismos para conseguir isto é criar a instância com um bloco C# using (Using no Visual Basic), o que garante que o Dispose método para o escritor é invocado, resultando no encerramento correto da instância.

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

O código seguinte 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 destas soluções puder ser usada (por exemplo, se a StreamWriter for armazenada numa variável estática e não for possível executar código facilmente no final da sua vida útil), então chamar Flush após StreamWriter a sua última utilização ou definir a AutoFlush propriedade para true antes da sua primeira utilização deve evitar este 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 no tempo de execução.

Output

Uma mensagem a indicar que esta violação ocorreu.

Configuração

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

Consulte também