Pergunta

Em C#/. Net (no Windows), existe uma maneira de ler um arquivo "cultivo" usando um fluxo de arquivo? O comprimento do arquivo será muito pequeno quando o Filestream for aberto, mas o arquivo será gravado por outro thread. Se/quando o FileStream "alcança" o outro tópico (ou seja, quando Read() Retorna 0 bytes Leia), quero pausar para permitir que o arquivo buffer um pouco e continue lendo.

Eu realmente não quero usar um FilesystemWatcher e continue criando novos fluxos de arquivo (como foi sugerido para arquivos de log), pois este não é um arquivo de log (é um arquivo de vídeo que está sendo codificado em tempo real) e o desempenho é um problema.

Obrigado,
Robert

Foi útil?

Solução

Você pode fazer isso, mas precisa acompanhar cuidadosamente o arquivo de leitura e gravação de posições usando Stream.Seek e com a sincronização apropriada entre os threads. Normalmente você usaria um EventWaitHandle ou sua subclasse para fazer a sincronização para dados, e você também precisaria considerar a sincronização para o acesso ao FileStream o próprio objeto (provavelmente por meio de um lock declaração).

Atualizar: Em responder essa questão Implementei algo semelhante - uma situação em que um arquivo estava sendo baixado em segundo plano e também sendo carregado ao mesmo tempo. Eu usei buffers de memória e publiquei um essência que tem código de trabalho. (É GPL, mas isso pode não importar para você - em qualquer caso, você pode usar os princípios para fazer suas próprias coisas.)

Outras dicas

A maneira como eu resolvi isso é usar o DirectoryWatcher / FileSystemWatcher Class e, quando desencadeia o arquivo que você deseja, você abra uma transmissão file e a leia até o final. E quando terminar de ler, salvo a posição do leitor, então da próxima vez DirectoryWatcher / FileSystemwatcher gatilhos Eu abro um fluxo Definir a posição para onde estava da última vez.

Chamando filestream.length é realmente muito lento, não tive problemas de desempenho com minha solução (eu estava lendo um "log" que varia de 10 MB a 50 ISH).

Para mim, a solução que descrevo é muito simples e fácil de manter, eu tentaria e perfilava. Eu não acho que você terá problemas de desempenho com base nisso. Faço isso quando as pessoas estão jogando um jogo com vários roscas, levando toda a sua CPU e ninguém reclamou que meu analisador é mais exigente do que os analisadores concorrentes.

Isso funcionou com um fluxo de fluxo em torno de um arquivo, com as seguintes etapas:

  1. No programa que grava no arquivo, abra -o com o compartilhamento de leitura, assim:

    var out = new StreamWriter(File.Open("logFile.txt",  FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read));
    
  2. No programa que lê o arquivo, abra-o com o compartilhamento de leitura e gravação, como este:

    using (FileStream fileStream = File.Open("logFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using ( var file = new StreamReader(fileStream))
    
  3. Antes de acessar o fluxo de entrada, verifique se o final foi atingido e, em caso afirmativo, espere um pouco.

    while (file.EndOfStream)
    {
        Thread.Sleep(5);
    }
    

Outra coisa que pode ser útil é que a classe FileStream possui uma propriedade chamada ReadTimeout, que é definida como:

Obtém ou define um valor, em milissegundos, que determina quanto tempo o fluxo tentará ler antes de tempo. (herdado do fluxo)

Isso pode ser útil, pois, quando suas leituras, o seu tópico executa as leituras pode fazer uma pausa enquanto o buffer de gravação for liberado. Vale a pena escrever um pequeno teste para ver se essa propriedade ajudaria sua causa de alguma forma.

As operações de leitura e gravação estão acontecendo no mesmo objeto? Nesse caso, você pode escrever suas próprias abstrações sobre o arquivo e, em seguida, escreva o código de comunicação cruzado, de modo que o tópico que esteja executando as gravações e notifique o thread executando as leituras quando for feito para que o tópico que faz as leituras saiba quando parar de ler leia Quando atinge o EOF.

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