다음을 통해 공유


파일 액세스에 Async 사용(C# 및 Visual Basic)

사용할 수 있는 비동기 파일 액세스 기능.비동기 기능을 사용 하 여 콜백을 사용 하거나 여러 메서드 또는 람다 식 코드를 분할 하지 않고에 비동기 메서드를 호출할 수 있습니다.비동기 동기 코드를 만들려면 하면 방금 대신 동기 메서드를 비동기 메서드 호출 및 코드에 몇 가지 키워드를 추가 합니다.

다음과 같은 이유로 파일 액세스 호출을 숙지 추가 고려해 야 합니다.

  • UI 스레드에서 작업을 실행 다른 작업을 수행할 수 있으므로 숙지 UI 응용 프로그램을 응답성 있습니다.UI 스레드에서 코드를 실행 해야 하는 경우는 (예를 들어, 50 개 이상의 밀리초) 오랜 시간이 걸립니다, 그리고 UI는 I/O가 완료 되 고 UI 스레드는 다시 처리할 키보드 및 마우스 입력 및 다른 이벤트까지 중지 될 수 있습니다.

  • 숙지 ASP.NET의 확장성 및 기타 서버 기반 응용 프로그램 스레드에 대 한 필요성을 줄임으로써 향상 됩니다.천 스레드가 전용된 스레드 당 응답 응용 프로그램을 사용 하 여 수천 요청이 동시에 처리 되는 경우 필요 합니다.종종 비동기 작업 스레드가 대기 중 사용할 필요가 없습니다.이들은 기존 I/O 완료 스레드 간단히 끝에 사용합니다.

  • 대기 시간 파일 액세스 작업을 현재 조건에서 매우 낮은 이지만 나중에 대기 시간이 크게 증가할 수 있습니다.예를 들어, 전 세계에 걸쳐 있는 서버에 파일을 이동할 수 있습니다.

  • 추가 오버 헤드의 비동기 기능을 사용 하 여이 작습니다.

  • 동시에 비동기 작업을 쉽게 실행할 수 있습니다.

예제를 실행합니다.

[!참고]

이 항목의 예제에 적용 되지 않는 Windows 스토어 는 응용 프로그램, Windows 8 전체 화면에 맞게 조정 하는 응용 프로그램 터치 상호 작용 합니다.비동기 파일 액세스에 사용 하는 방법에 대 한 내용은 Windows 스토어 응용 프로그램을 참조 하십시오. Windows 스토어 앱용 .NET 개요파일 및 스트림 I/O.파일 I/O에 대 한의 예 Windows 스토어 응용 프로그램을 다운로드할 수 있는 파일 액세스 샘플.

이 항목의 예제를 실행 하 여 만들 수 있습니다는 WPF 응용 프로그램 또는 Windows Forms 응용 프로그램 다음 추가 된 단추.단추에 Click 이벤트, 각 예제에서 첫 번째 메서드 호출을 추가 합니다.

다음 예제에서는 다음을 포함 Imports (Visual Basic) 또는 using (C#) 문.

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

FileStream 클래스 사용

이 항목 사용 예제는 FileStream 클래스를 운영 체제 수준에서 발생 하는 비동기 I/O를 유발 하는 옵션이 있습니다.이 옵션을 사용 하 여 스레드 풀 스레드가 대부분에서 차단 피할 수 있습니다.지정이 옵션을 사용 하 여 useAsync=true 또는 options=FileOptions.Asynchronous 생성자 호출에서 인수.

이 옵션을 사용할 수 없습니다 StreamReaderStreamWriter 해당 파일 경로 지정 하 여 직접 여는 경우.그러나 사용자가 제공 하는 경우이 옵션을 사용할 수 있습니다는 StreamFileStream 열 클래스.Note ThreadPool 스레드를 차단 하는 경우에 UI 스레드는 대기 중에 차단 되어 있지 않으므로 비동기 호출 UI 응용 프로그램에서 빠른 지.

텍스트 쓰기

다음 예제에서는 텍스트 파일에 씁니다.각 명령문을 기다립니다, 그리고 메서드를 즉시 종료 합니다.파일 I/O가 완료 되 면 메서드는 await 문 다음에 오는 문에서 다시 시작 합니다.Async 한정자를 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
public async void ProcessWrite()
{
    string filePath = @"temp2.txt";
    string text = "Hello World\r\n";

    await WriteTextAsync(filePath, text);
}

private async Task WriteTextAsync(string filePath, string text)
{
    byte[] encodedText = Encoding.Unicode.GetBytes(text);

    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Append, FileAccess.Write, FileShare.None,
        bufferSize: 4096, useAsync: true))
    {
        await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
    };
}

원래 예 문이 있는 await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);, 다음 두 문 중 한 축약형입니다.

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

첫 번째 문은 작업 반환 고 파일 처리를 시작 합니다.두 번째 명령문에는 await 메서드를 즉시 종료 하 고 다른 작업에서 반환 됩니다.파일을 나중에 처리 완료 되 면 실행 await를 다음에 오는 문으로 반환 됩니다.자세한 내용은 비동기 프로그램의 제어 흐름(C# 및 Visual Basic)연습: Async 메서드에 디버거 사용를 참조하십시오.

텍스트 읽기

다음 예제에서는 파일에서 텍스트를 읽습니다.텍스트 버퍼에 저장 했으며, 이런 경우에 StringBuilder.달리는 await 평가 값 앞의 예제를 만듭니다.ReadAsync 메서드 반환은 Task<Int32>, 평가 await의 생성은 Int32 값 (numRead) 작업 완료 후.자세한 내용은 비동기 반환 형식(C# 및 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
public async void ProcessRead()
{
    string filePath = @"temp2.txt";

    if (File.Exists(filePath) == false)
    {
        Debug.WriteLine("file not found: " + filePath);
    }
    else
    {
        try
        {
            string text = await ReadTextAsync(filePath);
            Debug.WriteLine(text);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

private async Task<string> ReadTextAsync(string filePath)
{
    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize: 4096, useAsync: true))
    {
        StringBuilder 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();
    }
}

비동기 I/O 병렬

다음 예제에서는 10 개의 텍스트 파일을 작성 하 여 병렬 처리 방법을 보여 줍니다.각 파일에는 WriteAsync 반환 작업을 다음 작업 목록에 추가 됩니다.await Task.WhenAll(tasks); 문은 메서드를 종료 하 고 이력서 파일 처리가 되 면 메서드 내에서 완료 작업에 대 한 모든.

닫습니다. 예제 FileStream 의 인스턴스는 finally 작업이 완료 된 후 차단 합니다.각 경우 FileStream 대신에 만들어진는 using 문의 FileStream 작업이 완료 되기 전에 삭제 될 수 있습니다.

성능 향상 된 병렬 처리 및 비동기 처리 않습니다 거의 완전히 있는지 note입니다.숙지의 장점은 여러 스레드를 묶어 두지 않기는 하 여 사용자 인터페이스 스레드를 묶어 두지 않기입니다.

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
public async void ProcessWriteMult()
{
    string folder = @"tempfolder\";
    List<Task> tasks = new List<Task>();
    List<FileStream> sourceStreams = new List<FileStream>();

    try
    {
        for (int index = 1; index <= 10; index++)
        {
            string text = "In file " + index.ToString() + "\r\n";

            string fileName = "thefile" + index.ToString("00") + ".txt";
            string filePath = folder + fileName;

            byte[] encodedText = Encoding.Unicode.GetBytes(text);

            FileStream sourceStream = new FileStream(filePath,
                FileMode.Append, FileAccess.Write, FileShare.None,
                bufferSize: 4096, useAsync: true);

            Task theTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
            sourceStreams.Add(sourceStream);

            tasks.Add(theTask);
        }

        await Task.WhenAll(tasks);
    }

    finally
    {
        foreach (FileStream sourceStream in sourceStreams)
        {
            sourceStream.Close();
        }
    }
}

사용 하는 경우는 WriteAsyncReadAsync 메서드를 지정할 수는 CancellationToken, 작업 중간에 취소할 수 있습니다.자세한 내용은 Async 응용 프로그램 미세 조정(C# 및 Visual Basic)관리되는 스레드의 취소를 참조하십시오.

참고 항목

작업

연습: Async 메서드에 디버거 사용

개념

Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)

비동기 반환 형식(C# 및 Visual Basic)

비동기 프로그램의 제어 흐름(C# 및 Visual Basic)