Frage

Ich habe eine Anwendung, die braucht, um eine Schleife durch alle Zeilen in text-Dateien, über Gigabyte groß.Einige dieser Dateien haben 10 s oder 100 s von Millionen von Zeilen.

Ein Beispiel meiner aktuellen (und synchron) zu Lesen, in etwa so aussieht wie...

  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...
      }
    }
  }

Ich habe einige Sachen über die .Netto-Asynchrone IO-streaming-Methoden, und ich bin nach etwas Hilfe mit 2-spezifische Fragen zu diesem Problem.

Zuerst bekomme ich eine Leistungssteigerung durch asyncronously Lesen dieser Dateien, wenn ich die entireity jeder Zeile, die ussually kurze, aber unterschiedlicher Länge (es gibt keine Beziehung zwischen den einzelnen Zeilen in der Datei)?

Zweitens, Wie wandle ich den code oben in einen asynchronen Lesen, so kann ich jede von Zeile zu Zeile, wie ich jetzt tun?

War es hilfreich?

Lösung

Anstatt die Zeile liest Async könnten Sie versuchen, die Datei liest Async.Das ist, umfassen Sie den code in Ihre Frage ein einziger Mitarbeiter delegieren.

    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...
                }
            }
        }
    }

Andere Tipps

Die async-Muster ist BeginRead()/EndRead().

Ob oder nicht Sie bekommen einen Schub, hängt viel, was sonst noch Los ist an der Zeit, die Sie tun, die liest.Ist es etwas anderes was Ihre app tun können, während der Wartezeit auf die liest?Wenn nicht, dann gehen async hilft nicht viel...

Asynchrone liest, wird am Ende nur das Kopf mehr haben wollen, für jeden block.Sie erhalten eine bessere Leistung boost von einem guten Defragmentierung der Dateien auf dem Dateisystem, und synchron gelesen.

Wie bereits erwähnt, die Versendung der Linie, die Verarbeitung zu anderen threads sollte einen Schub geben (insbesondere bei multi-core-CPUs)

Wenn die Leistung ist super-kritischen würde ich empfehlen, die Untersuchung interop für FILE_FLAG_SEQUENTIAL_SCAN Finden details hier

Noch besser schreiben Sie ein kleines C++ - app, die scannt die Datei mit der Flagge auf, um zu sehen, ob es die Leistung verbessert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top