Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az aszinkron funkcióval elérheti a fájlokat. Az aszinkron funkcióval visszahívások használata nélkül hívhat be aszinkron metódusokat, vagy feloszthatja a kódot több metódusra vagy lambda kifejezésre. Ha szinkron kódot szeretne aszinkronsá tenni, csak egy aszinkron metódust kell meghívnia szinkron metódus helyett, és hozzá kell adnia néhány kulcsszót a kódhoz.
Az aszinkron fájlelérési hívásokhoz való aszinkronizálás hozzáadásának következő okai lehetnek:
- Az aszinkronizálás rugalmasabbá teszi a felhasználói felületi alkalmazásokat, mert a műveletet elindító felhasználói felületi szál más műveleteket is végezhet. Ha a felhasználói felületi szálnak hosszú ideig tartó kódot kell végrehajtania (például több mint 50 ezredmásodpercet), a felhasználói felület lefagyhat, amíg az I/O be nem fejeződik, és a felhasználói felület szála újra feldolgozhatja a billentyűzet- és egérbemenetet, valamint egyéb eseményeket.
- Az aszinkronizálás javítja a ASP.NET és más kiszolgálóalapú alkalmazások méretezhetőségét azáltal, hogy csökkenti a szálak szükségességét. Ha az alkalmazás válaszonként dedikált szálat használ, és egyszerre ezer kérést kezel, ezer szálra van szükség. Az aszinkron műveleteknek gyakran nem kell szálat használniuk a várakozás során. A meglévő I/O-befejezési szálat rövid időre használják a végén.
- A fájlelérési műveletek késése a jelenlegi körülmények között nagyon alacsony lehet, de a késés a jövőben jelentősen növekedhet. Előfordulhat például, hogy egy fájl átkerül egy olyan kiszolgálóra, amely a világ minden részén található.
- Az Async funkció használatának többletterhelése kicsi.
- Az aszinkron feladatok egyszerűen futtathatók párhuzamosan.
Megfelelő osztályok használata
A témakör egyszerű példái a és File.ReadAllTextAsynca példákat mutatják beFile.WriteAllTextAsync. A fájl I/O-műveleteinek finom szabályozásához használja a FileStream osztályt, amely lehetővé teszi az aszinkron I/O-műveletek az operációs rendszer szintjén történő előfordulását. Ezzel a beállítással sok esetben elkerülheti a szálkészletszál blokkolását. A beállítás engedélyezéséhez adja meg a vagy options=FileOptions.Asynchronous argumentumot useAsync=true a konstruktorhívásban.
Ezt a lehetőséget nem használhatja a-val StreamReader , és StreamWriter ha közvetlenül egy fájlelérési út megadásával nyitja meg őket. Ezt a lehetőséget azonban akkor is használhatja, ha olyan értéket Stream ad meg nekik, amelyet az FileStream osztály megnyitott. Az aszinkron hívások akkor is gyorsabbak a felhasználói felületi alkalmazásokban, ha egy szálkészlet-szál le van tiltva, mivel a felhasználói felületi szál nem lesz blokkolva a várakozás során.
Szöveg írása
Az alábbi példák szöveget írnak egy fájlba. Minden várakozási utasításnál a metódus azonnal kilép. Ha az I/O fájl elkészült, a metódus a await utasítást követő utasításban folytatódik. Az aszinkron módosító az await utasítást használó metódusok definíciójában van.
Egyszerű példa
public async Task SimpleWriteAsync()
{
string filePath = "simple.txt";
string text = $"Hello World";
await File.WriteAllTextAsync(filePath, text);
}
Véges vezérlőelem-példa
public async Task ProcessWriteAsync()
{
string filePath = "temp.txt";
string text = $"Hello World{Environment.NewLine}";
await WriteTextAsync(filePath, text);
}
async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using var sourceStream =
new FileStream(
filePath,
FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true);
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
}
Az eredeti példában a utasítás await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);szerepel, amely a következő két utasítás összehúzódása:
Task theTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
await theTask;
Az első utasítás egy feladatot ad vissza, és elindítja a fájlfeldolgozást. A második várakozási utasítás hatására a metódus azonnal kilép, és egy másik feladatot ad vissza. Amikor a fájl feldolgozása később befejeződik, a végrehajtás visszatér a várakozást követő utasításhoz.
Szöveg felolvastatása
Az alábbi példák szövegeket olvasnak egy fájlból.
Egyszerű példa
public async Task SimpleReadAsync()
{
string filePath = "simple.txt";
string text = await File.ReadAllTextAsync(filePath);
Console.WriteLine(text);
}
Véges vezérlőelem-példa
A szöveg pufferelve van, és ebben az esetben egy StringBuilderfájlba kerül. Az előző példától eltérően a várakozás kiértékelése értéket ad. A ReadAsync metódus egyInt32<>Task értéket ad vissza, így a várakozás kiértékelése a művelet befejezése után értéket numRead ad vissza.Int32 További információ: Aszinkron visszatérési típusok (C#)..
public async Task ProcessReadAsync()
{
try
{
string filePath = "temp.txt";
if (File.Exists(filePath) != false)
{
string text = await ReadTextAsync(filePath);
Console.WriteLine(text);
}
else
{
Console.WriteLine($"file not found: {filePath}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
async Task<string> ReadTextAsync(string filePath)
{
using var sourceStream =
new FileStream(
filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true);
var sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
Párhuzamos aszinkron I/O
Az alábbi példák 10 szövegfájl megírásával szemléltetik a párhuzamos feldolgozást.
Egyszerű példa
public async Task SimpleParallelWriteAsync()
{
string folder = Directory.CreateDirectory("tempfolder").Name;
IList<Task> writeTaskList = new List<Task>();
for (int index = 11; index <= 20; ++ index)
{
string fileName = $"file-{index:00}.txt";
string filePath = $"{folder}/{fileName}";
string text = $"In file {index}{Environment.NewLine}";
writeTaskList.Add(File.WriteAllTextAsync(filePath, text));
}
await Task.WhenAll(writeTaskList);
}
Véges vezérlőelem-példa
A metódus minden fájlhoz visszaad egy feladatot, WriteAsync amelyet aztán hozzáad a tevékenységek listájához. A await Task.WhenAll(tasks); utasítás kilép a metódusból, és folytatódik a metóduson belül, amikor az összes feladat fájlfeldolgozása befejeződött.
A példa bezárja egy blokk összes FileStream példányát finally a feladatok befejezése után. Ha mindegyik FileStream egy utasításban using lett létrehozva, a FileStream művelet befejezése előtt a rendszer elvetheti őket.
A teljesítménynövelés szinte teljes egészében a párhuzamos feldolgozásból származik, nem az aszinkron feldolgozásból. Az aszinkronizálás előnye, hogy nem köt össze több szálat, és nem köti össze a felhasználói felület szálát.
public async Task ProcessMultipleWritesAsync()
{
IList<FileStream> sourceStreams = new List<FileStream>();
try
{
string folder = Directory.CreateDirectory("tempfolder").Name;
IList<Task> writeTaskList = new List<Task>();
for (int index = 1; index <= 10; ++ index)
{
string fileName = $"file-{index:00}.txt";
string filePath = $"{folder}/{fileName}";
string text = $"In file {index}{Environment.NewLine}";
byte[] encodedText = Encoding.Unicode.GetBytes(text);
var sourceStream =
new FileStream(
filePath,
FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true);
Task writeTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
sourceStreams.Add(sourceStream);
writeTaskList.Add(writeTask);
}
await Task.WhenAll(writeTaskList);
}
finally
{
foreach (FileStream sourceStream in sourceStreams)
{
sourceStream.Close();
}
}
}
A és ReadAsync a WriteAsync metódusok használatakor megadhat egy CancellationTokenelemet, amellyel megszakíthatja a műveletet a stream közepén. További információ: Megszakítás felügyelt szálakban.