UPDATE: Asincrono versioni di File.ReadAll[Lines|Bytes|Text]
, File.AppendAll[Lines|Text]
e File.WriteAll[Lines|Bytes|Text]
sono ormai merged into .NET Core. Si spera che questi metodi vengano portati su .NET Framework, Mono ecc. E inseriti in una versione futura di .NET Standard.
Utilizzo di Task.Run
, che è essenzialmente un wrapper per Task.Factory.StartNew
, per wrapper asincroni is a code smell.
Se non si vuole perdere un filo di CPU utilizzando una funzione di blocco, si dovrebbe attendere un metodo veramente asincrona IO, StreamReader.ReadToEndAsync
, in questo modo:
using (var reader = File.OpenText("Words.txt"))
{
var fileText = await reader.ReadToEndAsync();
// Do something with fileText...
}
questo otterrà l'intero file come string
anziché List<string>
. Se avete bisogno di linee, invece, si potrebbe facilmente dividere la stringa in seguito, in questo modo:
using (var reader = File.OpenText("Words.txt"))
{
var fileText = await reader.ReadToEndAsync();
return fileText.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
}
EDIT: Ecco alcuni metodi per ottenere lo stesso codice come File.ReadAllLines
, ma in un modo veramente asincrono. Il codice si basa sulla realizzazione di File.ReadAllLines
stessa:
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();
}
}
Che dire se si inizia rimuovendo la chiamata non necessaria a ToList() che creerà una copia dell'array di stringhe? –
@JbEvain - Per essere pedante, 'ToList()' non copia semplicemente l'array, ma crea un 'List'. Senza ulteriori informazioni non si può ritenere che non sia necessario, dal momento che forse "// fa qualcosa con s" "chiama i metodi' List'. – Mike