从快速增长的文件等待下一行的最佳方法是什么?

时间:2017-04-07 08:28:31

标签: c# io

我需要阅读快速增长的测试文件,并尽快处理任何新行。 该文件可以每毫秒更新几次。

  1. 如果我在“PROBLEM”代码行中引入睡眠(如下所示),它可以很好地工作,但会引入1毫秒的延迟。

  2. 如果我注释掉“问题”行,我没有延迟,但我的CPU使用率达到了70%。

  3. 有更好的方法可以解决这个问题吗?

    public void UpdatePricesFromSFile()
    {
        using (txtFileReader = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
        {
            txtFileReader.BaseStream.Seek(0, SeekOrigin.End);
            while (true)
            {
                while ((line = txtFileReader.ReadLine()) == null)
                {
                    System.Threading.Thread.Sleep(1); //PROBLEM
                }
                //Process line
            }
        }
    }
    

1 个答案:

答案 0 :(得分:0)

使用代码示例扩展我的评论:

public abstract class FileWatcher
{
    // last known position of the stream 
    int m_LastStreamPosition;

    // flag to check if file is currently in read state
    volatile bool m_IsReading;

    // info about the file
    FileInfo m_FileInfo;
    // file system watcher 
    FileSystemWatcher m_Watcher;

    // standard ctor used to watch specific file
    public FileWatcher(string filePath)
    {
        // create new instance of FileSystem using the path of the file
        m_FileInfo = new FileInfo(filePath);
        // if ( !m_FileInfo.Exists ) throw new InvalidArgumentException("filePath");
        // start watcher based on the FileInfo
        m_Watcher = new FileSystemWatcher(m_FileInfo.DirectoryName, m_FileInfo.Extension);
        m_Watcher.EnableRaisingEvents = true;
        m_Watcher.Changed += WhenFileChanged;

        // reset stream position and read file initialy
        m_LastStreamPosition = 0;
        ReadFile();
    }

    // event fired when file is changed
    // !! note that this will fire whenever you create file in the same
    //    directory as your desired file is and with the same extension
    //    and then change/modify this file
    void WhenFileChanged(object source, FileSystemEventArgs e)
    {
        // based on the note comment, check if that's our desired file
        if ( e.FullPath != m_FileInfo.FullName ) return;

        // refresh informations about the file
        m_FileInfo.Refresh();
        // check if something was added to the file,
        // in case something was removed (?) reset lastStreamPosition (?)
        if ( m_FileInfo.Length <= m_LastStreamPosition )
            m_LastStreamPosition = 0;

        // read the file
        ReadFile();
    }

    void ReadFile()
    {
        if ( m_IsReading ) return;

        m_IsReading = true;

        using ( StreamReader reader = m_FileInfo.OpenText() )
        {
            reader.BaseStream.Position = m_LastStreamPosition;
            string line = string.Empty;
            while ( ( line = reader.ReadLine() ) != null )
            {
                ProcessLine(line);
            }
            m_LastStreamPosition = reader.BaseStream.Position;
        }
        m_IsReading = false;
    }

    protected abstract void ProcessLine(string line);
}

样本用法:

public class MeFileWatcher
    : FileWatcher
{
    public MeFileWatcher(string filePath)
        : base(filePath)
    {
    }

    protected override void ProcessLine(string line)
    {
        Console.WriteLine ("NEW LINE ADDED -> {0}", line);
    }
}

MeFileWatcher meFileWatcher = new MeFileWatcher("D:\\testData\\meFile.txt");