我有一个应用程序需要遍历文本文件中的所有行,超过千兆字节。其中一些文件有10或100百万行。

我当前(和同步)阅读的一个例子,看起来像......

  using (FileStream stream = new FileStream(args[0], FileMode.Open, FileAccess.Read, FileShare.Read)) {
    using (StreamReader streamReader = new StreamReader(stream)) {
      string line;
      while (!string.IsNullOrEmpty(line = streamReader.ReadLine())) {           
        //do stuff with the line string...
      }
    }
  }

我已经阅读了一些关于.Net异步IO流方法的内容,我正在帮助解决有关此问题的两个具体问题。

首先,我是否会通过异步读取这些文件来获得性能提升,如果我需要每行的完整性,这些文章很短,但长度不同(文件中的每一行之间没有关系)?

其次,如何将上面的代码转换为异步读取,这样我就能像现在一样逐行处理?

有帮助吗?

解决方案

您可能会尝试使该文件读取异步,而不是让该行读取异步。这包含了单个工作人员代表中问题中的所有代码。

    static void Main(string[] args)
    {
        WorkerDelegate worker = new WorkerDelegate(Worker);
        // Used for thread and result management.
        List<IAsyncResult> results = new List<IAsyncResult>();
        List<WaitHandle> waitHandles = new List<WaitHandle>();

        foreach (string file in Directory.GetFiles(args[0], "*.txt"))
        {
            // Start a new thread.
            IAsyncResult res = worker.BeginInvoke(file, null, null);
            // Store the IAsyncResult for that thread.
            results.Add(res);
            // Store the wait handle.
            waitHandles.Add(res.AsyncWaitHandle);
        }

        // Wait for all the threads to complete.
        WaitHandle.WaitAll(waitHandles.ToArray(), -1, false); // for < .Net 2.0 SP1 Compatibility

        // Gather all the results.
        foreach (IAsyncResult res in results)
        {
            try
            {
                worker.EndInvoke(res);
                // object result = worker.EndInvoke(res); // For a worker with a result.
            }
            catch (Exception ex)
            {
                // Something happened in the thread.
            }
        }
    }

    delegate void WorkerDelegate(string fileName);
    static void Worker(string fileName)
    {
        // Your code.
        using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            using (StreamReader streamReader = new StreamReader(stream))
            {
                string line;
                while (!string.IsNullOrEmpty(line = streamReader.ReadLine()))
                {
                    //do stuff with the line string...
                }
            }
        }
    }

其他提示

异步模式是BeginRead()/ EndRead()。

你是否获得提升取决于你在读取时还有什么进展。你的应用程序在等待读取时可以做些什么吗?如果没有,那么去异步将无济于事......

异步读取最终会使磁头为每个块寻找更多。通过对文件系统上的文件进行良好的碎片整理并使用同步读取,您将获得更好的性能提升。

正如已经指出的那样,将线路处理调度到其他线程应该会提升(特别是在多核CPU上)

如果性能超级关键我建议调查interop for FILE_FLAG_SEQUENTIAL_SCAN 参见此处的详细信息

最好还是写一个小的C ++应用程序,用该标志扫描文件,看看它是否能提高性能。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top