Pergunta

Eu tenho esse código que salva um arquivo PDF.

FileStream fs = new FileStream(SaveLocation, FileMode.Create);
fs.Write(result.DocumentBytes, 0, result.DocumentBytes.Length);
fs.Flush();
fs.Close();

Funciona bem. No entanto, às vezes, ele não libera o bloqueio imediatamente e isso faz com que exceções de travamento de arquivos com funções sejam executadas após esta execução.

Existe uma maneira ideal de liberar o bloqueio do arquivo logo depois a fs.close ()

Foi útil?

Solução

Aqui está o ideal:

using (var fs = new FileStream(SaveLocation, FileMode.Create))
{
    fs.Write(result.DocumentBytes, 0, result.DocumentBytes.Length);
}

que é aproximadamente equivalente a:

FileStream fs =  null;
try
{
    fs = new FileStream(SaveLocation, FileMode.Create);
    fs.Write(result.DocumentBytes, 0, result.DocumentBytes.Length);
}
finally
{
    if (fs != null)
    {
        ((IDisposable)fs).Dispose();
    }
}

a usando sendo mais legível.


ATUALIZAR:

@aron, agora que estou pensando

File.WriteAllBytes(SaveLocation, result.DocumentBytes);

Parece ainda mais bonito aos olhos do que o ideal :-)

Outras dicas

Vimos esse mesmo problema na produção com uma declaração usando () envolvendo -a.

Um dos principais culpados aqui é o software antivírus que pode se esgueirar depois que o arquivo é fechado, pegue-o para verificar que ele não contém um vírus antes de liberá-lo.

Mas mesmo com todo o software antivírus fora do mix, em sistemas de carga muito alta com arquivos armazenados em compartilhamentos de rede, ainda vimos o problema ocasionalmente. A, tosse, thread curto.sleep (), tosse, depois que o fechamento parecia curá -lo. Se alguém tiver uma solução melhor, eu adoraria ouvir!

Não consigo imaginar por que o bloqueio seria mantido após o fechamento do arquivo. Mas você deve considerar envolver isso em uma declaração de uso para garantir que o arquivo seja fechado, mesmo que uma exceção seja levantada

using (FileStream fs = new FileStream(SaveLocation, FileMode.Create))
{
  fs.Write(result.DocumentBytes, 0, result.DocumentBytes.Length);  
}

Se as funções que executam após esta fazem parte do mesmo aplicativo, uma abordagem melhor pode ser abrir o arquivo para leitura/gravação no início de todo o processo e depois passar o arquivo para cada função sem fechá -lo até que o final do processo. Em seguida, será desnecessário que o aplicativo bloqueie a espera da operação de IO.

Isso funcionou para mim ao usar .flush () Eu tive que adicionar um fechamento dentro da instrução usando.

 using (var imageFile = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite,FileShare.ReadWrite))
 {
     imageFile.Write(bytes, 0, bytes.Length);
     imageFile.Flush();
     imageFile.Close();
  }

Acabei de ter o mesmo problema quando fechei uma transmissão e abri o arquivo imediatamente em outra classe. A declaração de uso não era uma solução, pois o FileStream havia sido criado em outro local e armazenado em uma lista. Limpar a lista não foi suficiente.

Parece que o fluxo precisa ser libertado pelo coletor de lixo antes que o arquivo possa ser reutilizado. Se o tempo entre fechar e abrir for muito curto, você pode usar

GC.Collect();

Logo depois de fechar o fluxo. Isso funcionou para mim.

Eu acho que as soluções de Ian Mercer para colocar o tópico para dormir podem ter o mesmo efeito, dando ao GC tempo para libertar os recursos.

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