web-dev-qa-db-ger.com

Wie kann ich Files.ReadAllLines synchronisieren und auf Ergebnisse warten?

Ich habe den folgenden Code,

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        button1.IsEnabled = false;

        var s = File.ReadAllLines("Words.txt").ToList(); // my WPF app hangs here
        // do something with s

        button1.IsEnabled = true;
    }

Words.txt hat eine Menge Wörter, die ich in die Variable s eingelesen habe. Ich versuche, async und await-Schlüsselwörter in C # 5 zu verwenden, wobei Async CTP Library verwendet wird, damit die WPF-App nicht hängen bleibt. Bisher habe ich den folgenden Code,

    private async void button1_Click(object sender, RoutedEventArgs e)
    {
        button1.IsEnabled = false;

        Task<string[]> ws = Task.Factory.FromAsync<string[]>(
            // What do i have here? there are so many overloads
            ); // is this the right way to do?

        var s = await File.ReadAllLines("Words.txt").ToList();  // what more do i do here apart from having the await keyword?
        // do something with s

        button1.IsEnabled = true;
    }

Das Ziel ist, die Datei asynchron und nicht synchron zu lesen, um ein Einfrieren der WPF-App zu vermeiden.

Jede Hilfe wird geschätzt, danke!

53
user677607

UPDATE: Async-Versionen von File.ReadAll[Lines|Bytes|Text] , File.AppendAll[Lines|Text] und File.WriteAll[Lines|Bytes|Text] wurden jetzt in .NET Core zusammengeführt . Diese Methoden werden hoffentlich auf .NET Framework, Mono usw. portiert und in eine zukünftige Version von .NET Standard übernommen.

Verwenden von Task.Run, das im Wesentlichen ein Wrapper für Task.Factory.StartNew ist, für asynchrone Wrapper ist ein Codegeruch

Wenn Sie einen CPU-Thread nicht durch Verwendung einer Blockierungsfunktion verschwenden möchten, sollten Sie auf eine wirklich asynchrone Methode IO StreamReader.ReadToEndAsync wie folgt warten:

using (var reader = File.OpenText("Words.txt"))
{
    var fileText = await reader.ReadToEndAsync();
    // Do something with fileText...
}

Dadurch wird die gesamte Datei als string anstelle von List<string> abgerufen. Wenn Sie stattdessen Linien benötigen, können Sie die Zeichenfolge anschließend einfach aufteilen:

using (var reader = File.OpenText("Words.txt"))
{
    var fileText = await reader.ReadToEndAsync();
    return fileText.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
}

EDIT: Hier sind einige Methoden, um denselben Code wie File.ReadAllLines zu erreichen, jedoch auf wirklich asynchrone Weise. Der Code basiert auf der Implementierung von File.ReadAllLines selbst:

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

public static class FileEx
{
    /// <summary>
    /// This is the same default buffer size as
    /// <see cref="StreamReader"/> and <see cref="FileStream"/>.
    /// </summary>
    private const int DefaultBufferSize = 4096;

    /// <summary>
    /// Indicates that
    /// 1. The file is to be used for asynchronous reading.
    /// 2. The file is to be accessed sequentially from beginning to end.
    /// </summary>
    private const FileOptions DefaultOptions = FileOptions.Asynchronous | FileOptions.SequentialScan;

    public static Task<string[]> ReadAllLinesAsync(string path)
    {
        return ReadAllLinesAsync(path, Encoding.UTF8);
    }

    public static async Task<string[]> ReadAllLinesAsync(string path, Encoding encoding)
    {
        var lines = new List<string>();

        // Open the FileStream with the same FileMode, FileAccess
        // and FileShare as a call to File.OpenText would've done.
        using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, DefaultOptions))
        using (var reader = new StreamReader(stream, encoding))
        {
            string line;
            while ((line = await reader.ReadLineAsync()) != null)
            {
                lines.Add(line);
            }
        }

        return lines.ToArray();
    }
}
107
khellang

Verwenden Sie Stream.ReadAsync zum asynchronen Lesen der Datei. 

private async void Button_Click(object sender, RoutedEventArgs e)
{
    string filename = @"c:\Temp\userinputlog.txt";
    byte[] result;

    using (FileStream SourceStream = File.Open(filename, FileMode.Open))
    {
        result = new byte[SourceStream.Length];
        await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
    }

    UserInput.Text = System.Text.Encoding.ASCII.GetString(result);
}

Lesen Sie MSDN Stream.ReadAsync

0
Mak Ahmed