Sdílet prostřednictvím


Použití Async pro přístup k souborům (Visual Basic)

K přístupu k souborům můžete použít funkci Async. Pomocí funkce Async můžete volat asynchronní metody bez použití zpětného volání nebo rozdělení kódu mezi více metod nebo výrazů lambda. Pokud chcete, aby synchronní kód byl asynchronní, stačí místo synchronní metody volat asynchronní metodu a přidat do kódu několik klíčových slov.

Můžete zvážit následující důvody přidání asynchrony do volání přístupu k souborům:

  • Asynchrony zvyšuje odezvu aplikací uživatelského rozhraní, protože vlákno uživatelského rozhraní, které spouští operaci, může provádět jinou práci. Pokud vlákno uživatelského rozhraní musí spouštět kód, který trvá dlouhou dobu (například více než 50 milisekund), uživatelské rozhraní se může ukotvit, dokud se vstupně-výstupní operace nezačne dokončit a vlákno uživatelského rozhraní může znovu zpracovat vstup klávesnice a myš a další události.

  • Asynchrony zlepšuje škálovatelnost ASP.NET a dalších serverových aplikací tím, že snižuje potřebu vláken. Pokud aplikace používá vyhrazené vlákno na odpověď a současně zpracovává tisíce požadavků, je potřeba tisíc vláken. Asynchronní operace často nemusí během čekání používat vlákno. Použijí existující vlákno pro doplňování vstupně-výstupních operací krátce na konci.

  • Latence operace přístupu k souboru může být za aktuálních podmínek velmi nízká, ale latence se může v budoucnu výrazně zvýšit. Soubor se například může přesunout na server, který je po celém světě.

  • Přidaná režie při používání funkce Async je malá.

  • Asynchronní úlohy je možné snadno spustit paralelně.

Spuštění příkladů

Pokud chcete spustit příklady v tomto tématu, můžete vytvořit aplikaci WPF nebo aplikaci model Windows Forms a pak přidat tlačítko. V události tlačítka Click přidejte volání první metody v každém příkladu.

V následujících příkladech uveďte následující Imports příkazy.

Imports System  
Imports System.Collections.Generic  
Imports System.Diagnostics  
Imports System.IO  
Imports System.Text  
Imports System.Threading.Tasks  

Použití třídy FileStream

Příklady v tomto tématu používají FileStream třídu, která má možnost, která způsobuje, že asynchronní vstupně-výstupní operace na úrovni operačního systému. Pomocí této možnosti se můžete vyhnout blokování vlákna ThreadPool v mnoha případech. Chcete-li tuto možnost povolit, zadáte useAsync=true hodnotu nebo options=FileOptions.Asynchronous argument ve volání konstruktoru.

Tuto možnost StreamReader nemůžete použít a StreamWriter pokud je otevřete přímo zadáním cesty k souboru. Tuto možnost však můžete použít, pokud jim Stream zadáte, že FileStream byla třída otevřena. Všimněte si, že asynchronní volání jsou v aplikacích uživatelského rozhraní rychlejší, i když je vlákno ThreadPool blokováno, protože vlákno uživatelského rozhraní není během čekání blokováno.

Psaní textu

Následující příklad zapíše text do souboru. V každém příkazu await metoda okamžitě ukončí. Po dokončení vstupně-výstupních operací se metoda obnoví v příkazu, který následuje za příkazem await. Všimněte si, že modifikátor async je v definici metod, které používají příkaz await.

Public Async Sub ProcessWrite()  
    Dim filePath = "temp2.txt"  
    Dim text = "Hello World" & ControlChars.CrLf  
  
    Await WriteTextAsync(filePath, text)  
End Sub  
  
Private Async Function WriteTextAsync(filePath As String, text As String) As Task  
    Dim encodedText As Byte() = Encoding.Unicode.GetBytes(text)  
  
    Using sourceStream As New FileStream(filePath,  
        FileMode.Append, FileAccess.Write, FileShare.None,  
        bufferSize:=4096, useAsync:=True)  
  
        Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length)  
    End Using  
End Function  

Původní příklad obsahuje příkaz Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length), což je kontrakt následujících dvou příkazů:

Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)  
Await theTask  

První příkaz vrátí úlohu a způsobí spuštění zpracování souborů. Druhý příkaz s příkazem await způsobí, že metoda okamžitě ukončí a vrátí jiný úkol. Po dokončení zpracování souboru se spuštění vrátí do příkazu, který následuje za příkazem await. Další informace naleznete v tématu Tok řízení v asynchronních programech (Visual Basic).

Čtení textu

Následující příklad načte text ze souboru. Text je uložen do vyrovnávací paměti a v tomto případě je umístěn do .StringBuilder Na rozdíl od předchozího příkladu vytvoří vyhodnocení operátoru await hodnotu. Metoda ReadAsync vrátí hodnotuInt32<>Task , takže vyhodnocení await vytvoří Int32 hodnotu (numRead) po dokončení operace. Další informace naleznete v tématu Asynchronní návratové typy (Visual Basic).

Public Async Sub ProcessRead()  
    Dim filePath = "temp2.txt"  
  
    If File.Exists(filePath) = False Then  
        Debug.WriteLine("file not found: " & filePath)  
    Else  
        Try  
            Dim text As String = Await ReadTextAsync(filePath)  
            Debug.WriteLine(text)  
        Catch ex As Exception  
            Debug.WriteLine(ex.Message)  
        End Try  
    End If  
End Sub  
  
Private Async Function ReadTextAsync(filePath As String) As Task(Of String)  
  
    Using sourceStream As New FileStream(filePath,  
        FileMode.Open, FileAccess.Read, FileShare.Read,  
        bufferSize:=4096, useAsync:=True)  
  
        Dim sb As New StringBuilder  
  
        Dim buffer As Byte() = New Byte(&H1000) {}  
        Dim numRead As Integer  
        numRead = Await sourceStream.ReadAsync(buffer, 0, buffer.Length)  
        While numRead <> 0  
            Dim text As String = Encoding.Unicode.GetString(buffer, 0, numRead)  
            sb.Append(text)  
  
            numRead = Await sourceStream.ReadAsync(buffer, 0, buffer.Length)  
        End While  
  
        Return sb.ToString  
    End Using  
End Function  

Paralelní asynchronní vstupně-výstupní operace

Následující příklad ukazuje paralelní zpracování zápisem 10 textových souborů. Pro každý soubor WriteAsync vrátí metoda úkol, který se pak přidá do seznamu úkolů. Příkaz Await Task.WhenAll(tasks) ukončí metodu a obnoví v rámci metody, když je zpracování souboru dokončeno pro všechny úlohy.

Příklad po dokončení úkolů zavře všechny FileStream instance v Finally bloku. Pokud se každý z nich FileStream vytvořil v Imports příkazu, FileStream může být uvolněn před dokončením úkolu.

Všimněte si, že zvýšení výkonu téměř zcela pochází z paralelního zpracování, nikoli asynchronního zpracování. Výhodou asynchrony je, že neváže více vláken a že neváže vlákno uživatelského rozhraní.

Public Async Sub ProcessWriteMult()  
    Dim folder = "tempfolder\"  
    Dim tasks As New List(Of Task)  
    Dim sourceStreams As New List(Of FileStream)  
  
    Try  
        For index = 1 To 10  
            Dim text = "In file " & index.ToString & ControlChars.CrLf  
  
            Dim fileName = "thefile" & index.ToString("00") & ".txt"  
            Dim filePath = folder & fileName  
  
            Dim encodedText As Byte() = Encoding.Unicode.GetBytes(text)  
  
            Dim sourceStream As New FileStream(filePath,  
                FileMode.Append, FileAccess.Write, FileShare.None,  
                bufferSize:=4096, useAsync:=True)  
  
            Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)  
            sourceStreams.Add(sourceStream)  
  
            tasks.Add(theTask)  
        Next  
  
        Await Task.WhenAll(tasks)  
    Finally  
        For Each sourceStream As FileStream In sourceStreams  
            sourceStream.Close()  
        Next  
    End Try  
End Sub  

Při použití a WriteAsyncReadAsync metod můžete zadat CancellationToken, který můžete použít ke zrušení operace uprostřed datového proudu. Další informace najdete v tématu Vyladění asynchronní aplikace (Visual Basic) a zrušení ve spravovaných vláknech.

Viz také