TAP(작업 기반 비동기 패턴)Task-based asynchronous pattern (TAP)

TAP(작업 기반 비동기 패턴)은 임의 비동기 작업을 나타내는 데 사용되는 System.Threading.Tasks.Task 네임스페이스의 System.Threading.Tasks.Task<TResult>System.Threading.Tasks 형식을 기준으로 합니다.The Task-based Asynchronous Pattern (TAP) is based on the System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> types in the System.Threading.Tasks namespace, which are used to represent arbitrary asynchronous operations. TAP은 새로운 개발을 위해 비동기 디자인 패턴을 권장합니다.TAP is the recommended asynchronous design pattern for new development.

이름 지정, 매개 변수 및 반환 형식Naming, parameters, and return types

TAP은 단일 메서드를 사용하여 비동기 작업의 시작과 완료를 나타냅니다.TAP uses a single method to represent the initiation and completion of an asynchronous operation. 이는 APM(비동기 프로그래밍 모델 또는 IAsyncResult) 패턴 및 EAP(이벤트 기반 비동기 패턴)와 대조됩니다.This contrasts with both the Asynchronous Programming Model (APM or IAsyncResult) pattern and the Event-based Asynchronous Pattern (EAP). APM에는 BeginEnd 메서드가 필요합니다.APM requires Begin and End methods. EAP에는 Async 접미사가 있는 메서드가 필요하며 하나 이상의 이벤트, 이벤트 처리기 대리자 형식 및 EventArg에서 파생된 형식도 필요합니다.EAP requires a method that has the Async suffix and also requires one or more events, event handler delegate types, and EventArg-derived types. TAP의 비동기 메서드는 Task, Task<TResult>, ValueTaskValueTask<TResult>와 같은 대기할 수 있는 형식을 반환하는 메서드의 작업 이름 뒤에 Async 접미사를 포함합니다.Asynchronous methods in TAP include the Async suffix after the operation name for methods that return awaitable types, such as Task, Task<TResult>, ValueTask, and ValueTask<TResult>. 예를 들어 Task<String>을 반환하는 비동기 Get 작업은 명명된 GetAsync일 수 있습니다.For example, an asynchronous Get operation that returns a Task<String> can be named GetAsync. 접미사가 Async인 EAP 메서드 이름이 이미 포함되어 있는 클래스에 TAP 메서드를 추가하는 경우 대신 TaskAsync 접미사를 사용합니다.If you're adding a TAP method to a class that already contains an EAP method name with the Async suffix, use the suffix TaskAsync instead. 예를 들어, 클래스에 GetAsync 메서드가 이미 있는 경우 이름으로 GetTaskAsync를 사용합니다.For example, if the class already has a GetAsync method, use the name GetTaskAsync. 메서드가 비동기 작업을 시작하지만 대기할 수 있는 형식을 반환하지 않는 경우 이 메서드가 작업 결과를 반환하거나 throw하지 않도록 제안하려면 해당 이름은 Begin, Start 또는 일부 다른 동사로 시작해야 합니다.If a method starts an asynchronous operation but does not return an awaitable type, its name should start with Begin, Start, or some other verb to suggest that this method does not return or throw the result of the operation.  

TAP 메서드는 해당 동기 메서드가 void를 반환하는지 또는 TResult 형식을 반환하는지에 따라 System.Threading.Tasks.Task 또는 System.Threading.Tasks.Task<TResult> 개체를 반환합니다.A TAP method returns either a System.Threading.Tasks.Task or a System.Threading.Tasks.Task<TResult>, based on whether the corresponding synchronous method returns void or a type TResult.

TAP 메서드의 매개 변수는 해당 동기 메서드의 매개 변수와 일치해야 하며 동일한 순서로 제공되어야 합니다.The parameters of a TAP method should match the parameters of its synchronous counterpart and should be provided in the same order. 그러나, outref 매개 변수는 이 규칙에서 제외되므로 사용하지 말아야 합니다.However, out and ref parameters are exempt from this rule and should be avoided entirely. out 또는 ref 매개 변수를 통해 반환된 데이터는 TResult에 의해 반환되는 Task<TResult>의 일부로 대신 반환되어야 하며, 여러 값을 수용하기 위해 튜플 또는 사용자 지정 데이터 구조를 사용해야 합니다.Any data that would have been returned through an out or ref parameter should instead be returned as part of the TResult returned by Task<TResult>, and should use a tuple or a custom data structure to accommodate multiple values. TAP 메서드의 동기 메서드가 매개 변수를 제공하지 않는 경우에도 CancellationToken 매개 변수 추가를 고려해야 합니다.You should also consider adding a CancellationToken parameter even if the TAP method's synchronous counterpart does not offer one.

작업의 생성, 조작 또는 조합에만 사용되는 메서드(메서드의 비동기 의도는 메서드 이름 또는 메서드가 속해 있는 형식의 이름에 분명하게 나타나 있음)는 이 명명 패턴을 따를 필요가 없습니다. 이런 메서드를 흔히 조합기라고 합니다. Methods that are devoted exclusively to the creation, manipulation, or combination of tasks (where the asynchronous intent of the method is clear in the method name or in the name of the type to which the method belongs) need not follow this naming pattern; such methods are often referred to as combinators. 조합기의 예로는 WhenAllWhenAny가 있으며, 작업 기반 비동기 패턴 사용 문서의 기본 제공 작업 기반 조합기 사용 섹션에서 해당 설명을 확인할 수 있습니다.Examples of combinators include WhenAll and WhenAny, and are discussed in the Using the Built-in Task-based Combinators section of the article Consuming the Task-based Asynchronous Pattern.

TAP 구문이 APM(비동기 프로그래밍 모델) 및 EAP(이벤트 기반 비동기 패턴)와 같은 레거시 비동기 프로그래밍 패턴에 사용된 구문과 어떻게 다른지에 대한 예를 보려면 비동기 프로그래밍 패턴을 참조하세요.For examples of how the TAP syntax differs from the syntax used in legacy asynchronous programming patterns such as the Asynchronous Programming Model (APM) and the Event-based Asynchronous Pattern (EAP), see Asynchronous Programming Patterns.

비동기 작업 시작Initiating an asynchronous operation

TAP을 기반으로 하는 비동기 메서드는 인수 유효성 검사 및 결과 작업을 반환하기 전에 비동기 작업 시작 등 적은 양의 작업을 동기적으로 수행할 수 있습니다.An asynchronous method that is based on TAP can do a small amount of work synchronously, such as validating arguments and initiating the asynchronous operation, before it returns the resulting task. 동기 작업은 비동기 메서드가 신속하게 반환할 수 있도록 최소한으로 유지해야 합니다.Synchronous work should be kept to the minimum so the asynchronous method can return quickly. 빠르게 반환되는 이유는 다음과 같습니다.Reasons for a quick return include the following:

  • 비동기 메서드는 사용자 인터페이스(UI) 스레드에서 호출할 수 있으며, 모든 장기 실행 동기 작업에서 애플리케이션의 응답에 문제가 발생할 수 있습니다Asynchronous methods may be invoked from user interface (UI) threads, and any long-running synchronous work could harm the responsiveness of the application.

  • 여러 비동기 메서드를 동시에 실행할 수 있습니다.Multiple asynchronous methods may be launched concurrently. 따라서 비동기 메서드의 동기 부분에서 모든 장기 실행 작업은 다른 비동기 작업의 시작을 지연시켜 동시성의 이점을 감소시킬 수 있습니다.Therefore, any long-running work in the synchronous portion of an asynchronous method could delay the initiation of other asynchronous operations, thereby decreasing the benefits of concurrency.

경우에 따라 작업을 완료하는 데 필요한 작업 시간이 비동기적으로 작업을 실행하는 데 필요한 작업 시간보다 적을 수 있습니다.In some cases, the amount of work required to complete the operation is less than the amount of work required to launch the operation asynchronously. 이미 메모리에 버퍼링된 데이터로 읽기 작업을 충족할 수 있는 스트림에서 읽기는 이러한 시나리오의 예입니다.Reading from a stream where the read operation can be satisfied by data that is already buffered in memory is an example of such a scenario. 경우에 따라 작업을 동기적으로 완료하고 이미 완료된 작업을 반환할 수 있습니다.In such cases, the operation may complete synchronously, and may return a task that has already been completed.

예외Exceptions

비동기 메서드는 사용 오류에 응답에서만 비동기 메서드 호출에서 throw할 예외를 발생시켜야 합니다.An asynchronous method should raise an exception to be thrown out of the asynchronous method call only in response to a usage error. 프로덕션 코드에서는 사용 오류가 절대 발생해서는 안 됩니다.Usage errors should never occur in production code. 예를 들어, null 참조(Visual Basic에서 Nothing)를 오류 상태(일반적으로 ArgumentNullException으로 표시되는 예외)를 유발하는 메서드 인수 중 하나로 전달하는 경우 null 참조가 전달되지 않도록 호출 코드를 수정할 수 있습니다.For example, if passing a null reference (Nothing in Visual Basic) as one of the method’s arguments causes an error state (usually represented by an ArgumentNullException exception), you can modify the calling code to ensure that a null reference is never passed. 기타 모든 오류에 대해 작업이 반환되기 전에 비동기 메서드가 완전하게 동기화되었다고 해도 비동기 메서드가 실행되는 동안 발생하는 예외를 반환된 작업에 할당해야 합니다.For all other errors, exceptions that occur when an asynchronous method is running should be assigned to the returned task, even if the asynchronous method happens to complete synchronously before the task is returned. 일반적으로 작업에는 최대 하나의 예외가 포함됩니다.Typically, a task contains at most one exception. 그러나 WhenAll과 같이 작업이 여러 작업을 나타내는 경우 여러 예외가 단일 작업에 연결될 수 있습니다.However, if the task represents multiple operations (for example, WhenAll), multiple exceptions may be associated with a single task.

대상 환경Target environment

TAP 메서드를 구현하면 비동기 실행이 발생하는 위치를 확인할 수 있습니다.When you implement a TAP method, you can determine where asynchronous execution occurs. 스레드 풀에서 워크로드를 실행하는 방법, 대부분의 작업 실행을 위한 스레드에 바인딩하지 않고 비동기 I/O를 사용하여 구현하는 방법, UI 스레드와 같은 특정 스레드를 실행하는 방법 또는 원하는 수의 잠재 컨텍스트를 사용하는 방법 중 선택할 수 있습니다.You may choose to execute the workload on the thread pool, implement it by using asynchronous I/O (without being bound to a thread for the majority of the operation’s execution), run it on a specific thread (such as the UI thread), or use any number of potential contexts. TAP 메서드는 실행할 항목이 없을 수도 있으며 시스템 내 다른 위치에서의 조건 발생을 나타내는 Task만 반환할 수도 있습니다(예: 큐에 대기 중인 데이터 구조에 도착하는 데이터를 나타내는 작업).A TAP method may even have nothing to execute, and may just return a Task that represents the occurrence of a condition elsewhere in the system (for example, a task that represents data arriving at a queued data structure).

TAP 메서드의 호출자는 결과 작업을 동기적으로 대기함으로써 TAP 메서드의 완료 대기를 차단하거나 비동기 작업이 완료될 때 추가(연속) 코드를 실행할 수 있습니다.The caller of the TAP method may block waiting for the TAP method to complete by synchronously waiting on the resulting task, or may run additional (continuation) code when the asynchronous operation completes. 연속 코드 작성자는 해당 코드가 실행되는 위치를 제어합니다.The creator of the continuation code has control over where that code executes. 연속 코드를 Task 클래스에서 메서드를 통해(예: ContinueWith) 명시적으로 만들거나 연속 작업을 기반으로 만들어진 언어 지원을 사용하여(예: C#의 await, Visual Basic의 Await, F#의 AwaitValue) 암시적으로 만들 수 있습니다.You may create the continuation code either explicitly, through methods on the Task class (for example, ContinueWith) or implicitly, by using language support built on top of continuations (for example, await in C#, Await in Visual Basic, AwaitValue in F#).

작업 상태Task status

Task 클래스는 비동기 작업에 대한 수명 주기를 제공하며 해당 주기는 TaskStatus 열거형으로 표시됩니다.The Task class provides a life cycle for asynchronous operations, and that cycle is represented by the TaskStatus enumeration. TaskTask<TResult>에서 파생되는 유형의 상황을 지원하거나 일정에 따라 구성을 구분할 수 있도록 지원하기 위해 Task 클래스가 Start 메서드를 노출합니다.To support corner cases of types that derive from Task and Task<TResult>, and to support the separation of construction from scheduling, the Task class exposes a Start method. 공용 Task 생성자에서 만든 작업은 예약되지 않은 Created 상태에서 수명 주기를 시작하고 이러한 인스턴스에서 Start를 호출할 때만 예약되므로 콜드 작업이라고 합니다. Tasks that are created by the public Task constructors are referred to as cold tasks, because they begin their life cycle in the non-scheduled Created state and are scheduled only when Start is called on these instances.

다른 모든 작업은 활성 상태로 수명 주기를 시작합니다. 즉, 작업이 나타내는 비동기 작업이 이미 시작되었고 작업 상태는 TaskStatus.Created 이외의 열거형 값임을 의미합니다.All other tasks begin their life cycle in a hot state, which means that the asynchronous operations they represent have already been initiated and their task status is an enumeration value other than TaskStatus.Created. TAP 메서드에서 반환되는 모든 작업을 활성화해야 합니다.All tasks that are returned from TAP methods must be activated. TAP 메서드가 내부적으로 작업의 생성자를 사용하여 반환할 작업을 인스턴스화하는 경우 해당 TAP 메서드는 작업을 반환하기 전에 Task 개체에서 Start를 호출해야 합니다.If a TAP method internally uses a task’s constructor to instantiate the task to be returned, the TAP method must call Start on the Task object before returning it. TAP 메서드의 소비자는 반환된 작업을 활성화했다가 안전하게 가정할 수 있으며 TAP 메서드에서 반환된 StartTask를 호출하려고 시도해서는 안 됩니다.Consumers of a TAP method may safely assume that the returned task is active and should not try to call Start on any Task that is returned from a TAP method. 활성 작업에서 Start를 호출하면 InvalidOperationException 예외가 나타납니다.Calling Start on an active task results in an InvalidOperationException exception.

취소(선택 사항)Cancellation (optional)

TAP에서 취소는 비동기 메서드 구현자와 비동기 메서드 소비자 모두에 대한 선택 사항입니다.In TAP, cancellation is optional for both asynchronous method implementers and asynchronous method consumers. 작업에서 취소를 허용하는 경우에는 취소 토큰(CancellationToken 인스턴스)을 수락하는 비동기 메서드의 오버로드가 표시됩니다.If an operation allows cancellation, it exposes an overload of the asynchronous method that accepts a cancellation token (CancellationToken instance). 관례적으로 매개 변수의 이름은 cancellationToken입니다.By convention, the parameter is named cancellationToken.

public Task ReadAsync(byte [] buffer, int offset, int count, 
                      CancellationToken cancellationToken)
Public Function ReadAsync(buffer() As Byte, offset As Integer, 
                          count As Integer, 
                          cancellationToken As CancellationToken) _ 
                          As Task

비동기 작업은 취소 요청에 대해 이 토큰을 모니터링합니다.The asynchronous operation monitors this token for cancellation requests. 취소 요청을 받으면 작업을 요청하고 취소하도록 선택할 수 있습니다.If it receives a cancellation request, it may choose to honor that request and cancel the operation. 작업이 완료되지 않은 상태로 취소되었다면, TAP 메서드는 Canceled 상태에서 종료된 작업을 반환합니다. 이 때, 사용 가능한 결과는 없으며 예외도 throw되지 않습니다.If the cancellation request results in work being ended prematurely, the TAP method returns a task that ends in the Canceled state; there is no available result and no exception is thrown. Canceled 상태는 FaultedRanToCompletion 상태와 함께 작업에 대한 최종(완료) 상태로 간주됩니다.The Canceled state is considered to be a final (completed) state for a task, along with the Faulted and RanToCompletion states. 따라서 작업이 Canceled 상태에 있을 경우 IsCompleted 속성은 true를 반환합니다.Therefore, if a task is in the Canceled state, its IsCompleted property returns true. Canceled 상태에서 작업이 완료되면 NotOnCanceled와 같은 연속 옵션이 연속을 취소하기 위해 지정되지 않는 한 작업이 등록된 모든 연속은 예정되거나 실행됩니다.When a task completes in the Canceled state, any continuations registered with the task are scheduled or executed, unless a continuation option such as NotOnCanceled was specified to opt out of continuation. 언어 기능의 사용을 통해 취소된 작업을 비동기적으로 대기하고 있는 코드는 실행을 계속하고 여기에서 파생되는 OperationCanceledException 또는 예외를 받습니다.Any code that is asynchronously waiting for a canceled task through use of language features continues to run but receives an OperationCanceledException or an exception derived from it. 또한 WaitWaitAll과 같은 메서드를 통해 작업에서 대기 중인 동기적으로 차단된 코드도 예외적으로 계속해서 실행합니다.Code that is blocked synchronously waiting on the task through methods such as Wait and WaitAll also continue to run with an exception.

토큰을 허용하는 TAP 메서드가 호출되기 전에 취소 토큰이 취소를 요청한 경우 TAP 메서드가 Canceled 작업을 반환해야 합니다.If a cancellation token has requested cancellation before the TAP method that accepts that token is called, the TAP method should return a Canceled task. 그러나 비동기 작업을 실행하는 동안 취소가 요청된 경우 비동기 작업에서 취소 요청을 허용해서는 안됩니다.However, if cancellation is requested while the asynchronous operation is running, the asynchronous operation need not accept the cancellation request. 반환된 작업은 작업이 취소 요청의 결과로 종료될 경우에만 Canceled 상태에서 종료되어야 합니다.The returned task should end in the Canceled state only if the operation ends as a result of the cancellation request. 취소가 요청되었지만 결과나 예외가 계속해서 발생하면 RanToCompletion 또는 Faulted 상태에서 작업을 종료해야 합니다.If cancellation is requested but a result or an exception is still produced, the task should end in the RanToCompletion or Faulted state.

무엇보다도 먼저 취소할 기능을 표시하려는 비동기 메서드의 경우 취소 토큰을 수락하지 않은 오버로드를 제공하지 않아도 됩니다.For asynchronous methods that want to expose the ability to be cancelled first and foremost, you don't have to provide an overload that doesn’t accept a cancellation token. 취소할 수 없는 메서드의 경우 취소 토큰을 수락하는 오버로드를 제공하지 마세요. 이렇게 하면 대상 메서드가 실제로 취소 가능한지 여부를 호출자에게 알려줍니다.For methods that cannot be canceled, do not provide overloads that accept a cancellation token; this helps indicate to the caller whether the target method is actually cancelable. 취소를 원하지 않는 소비자 코드는 CancellationToken을 허용하는 메서드를 호출하고 인수 값으로 None을 제공할 수도 있습니다.Consumer code that does not desire cancellation may call a method that accepts a CancellationToken and provide None as the argument value. None은 기본 CancellationToken과 기능적으로 동일합니다.None is functionally equivalent to the default CancellationToken.

진행률 보고(선택 사항)Progress reporting (optional)

일부 비동기 작업은 진행률 알림을 제공하여 이점을 얻습니다. 이는 일반적으로 비동기 작업의 진행률에 대한 정보로 사용자 인터페이스를 업데이트하는 데 사용됩니다.Some asynchronous operations benefit from providing progress notifications; these are typically used to update a user interface with information about the progress of the asynchronous operation.

TAP에서 일반적으로 IProgress<T>라고 이름이 지정된 매개 변수로 비동기 메서드에 전달되는 progress 인터페이스를 통해 진행이 처리됩니다.In TAP, progress is handled through an IProgress<T> interface, which is passed to the asynchronous method as a parameter that is usually named progress. 비동기 메서드를 호출할 때 진행률 인터페이스를 제공하면 작업을 시작한 후 잘못 등록된 이벤트 처리기가 업데이트를 누락시킬 수 있는 경우 잘못된 사용으로 인해 발생하는 경합 상태를 없앨 수 있습니다.Providing the progress interface when the asynchronous method is called helps eliminate race conditions that result from incorrect usage (that is, when event handlers that are incorrectly registered after the operation starts may miss updates). 더욱 중요한 것은 진행률 인터페이스에서 사용하는 코드에 따라 결정된 대로 다양한 진행률 구현을 지원한다는 점입니다.More importantly, the progress interface supports varying implementations of progress, as determined by the consuming code. 예를 들어, 현재 사용하고 있는 코드는 가장 최신 진행 상황 업데이트에만 관여하거나 모든 업데이트를 버퍼링하거나, 각 업데이트에 대한 작업을 호출하거나, 특정 스레드 호출이 마샬링되었는지 제어할 수 있습니다.For example, the consuming code may only care about the latest progress update, or may want to buffer all updates, or may want to invoke an action for each update, or may want to control whether the invocation is marshaled to a particular thread. 특정 소비자의 요구에 따라 맞춘 다양한 인터페이스의 구현을 통해 이러한 옵션을 모두 수행할 수 있습니다.All these options may be achieved by using a different implementation of the interface, customized to the particular consumer’s needs. 취소와 마찬가지로 API가 진행률 알림을 지원할 경우에만 TAP 구현에서 IProgress<T> 매개 변수를 제공해야 합니다.As with cancellation, TAP implementations should provide an IProgress<T> parameter only if the API supports progress notifications.

예를 들어, 지금까지는 이 문서 앞부분에서 설명한 ReadAsync 메서드가 바이트 리드 수의 형태로 중간 진행률을 보고할 수 있는 경우 진행률 콜백이 IProgress<T> 인터페이스일 수 있었습니다.For example, if the ReadAsync method discussed earlier in this article is able to report intermediate progress in the form of the number of bytes read thus far, the progress callback could be an IProgress<T> interface:

public Task ReadAsync(byte[] buffer, int offset, int count, 
                      IProgress<long> progress)
Public Function ReadAsync(buffer() As Byte, offset As Integer, 
                          count As Integer, 
                          progress As IProgress(Of Long)) As Task 

FindFilesAsync 메서드가 특정 검색 패턴을 충족하는 모든 파일의 목록을 반환하는 경우 진행률 콜백은 완료된 작업 비율과 부분 결과의 현재 집합에 관한 예측을 제공할 수 있습니다.If a FindFilesAsync method returns a list of all files that meet a particular search pattern, the progress callback could provide an estimate of the percentage of work completed as well as the current set of partial results. 튜플을 사용하여 이를 수행할 수 있습니다.It could do this either with a tuple:

public Task<ReadOnlyCollection<FileInfo>> FindFilesAsync(
            string pattern, 
            IProgress<Tuple<double, 
            ReadOnlyCollection<List<FileInfo>>>> progress)
Public Function FindFilesAsync(pattern As String, 
                               progress As IProgress(Of Tuple(Of Double, ReadOnlyCollection(Of List(Of FileInfo))))) _
                               As  Task(Of ReadOnlyCollection(Of FileInfo))

또는 API에 따라 달라지는 데이터 형식을 사용합니다.or with a data type that is specific to the API:

public Task<ReadOnlyCollection<FileInfo>> FindFilesAsync(
    string pattern, 
    IProgress<FindFilesProgressInfo> progress)
Public Function FindFilesAsync(pattern As String, 
                               progress As IProgress(Of FindFilesProgressInfo)) _
                               As Task(Of ReadOnlyCollection(Of FileInfo))

후자의 경우 일반적으로 특수 데이터 형식에 ProgressInfo 접미사가 붙습니다.In the latter case, the special data type is usually suffixed with ProgressInfo.

TAP 구현이 progress 매개 변수를 허용하는 오버로드를 제공하는 경우 진행률이 보고되지 않으면 null인 인수를 허용해야 합니다.If TAP implementations provide overloads that accept a progress parameter, they must allow the argument to be null, in which case no progress will be reported. TAP 구현에서는 비동기 메서드에서 신속하게 진행률을 제공하고 진행률의 소비자가 해당 정보를 다루는 방법과 가장 잘 처리할 수 있는 상황을 결정할 수 있는 Progress<T> 개체에 진행률을 동기적으로 보고해야 합니다.TAP implementations should report the progress to the Progress<T> object synchronously, which enables the asynchronous method to quickly provide progress, and allow the consumer of the progress to determine how and where best to handle the information. 예를 들어, 진행률 인스턴스에서 콜백 마샬링을 선택할 수 있으며, 캡처된 동기화 컨텍스트에 이벤트를 발생시킬 수 있습니다.For example, the progress instance could choose to marshal callbacks and raise events on a captured synchronization context.

IProgress<T> 구현IProgress<T> implementations

.NET Framework 4.5는 단일 IProgress<T> 구현인 Progress<T>를 제공합니다.The .NET Framework 4.5 provides a single IProgress<T> implementation: Progress<T>. Progress<T> 클래스는 다음과 같이 선언됩니다.The Progress<T> class is declared as follows:

public class Progress<T> : IProgress<T>  
{  
    public Progress();  
    public Progress(Action<T> handler);  
    protected virtual void OnReport(T value);  
    public event EventHandler<T> ProgressChanged;  
}  
Public Class Progress(Of T) : Inherits IProgress(Of T)  
    Public Sub New()  
    Public Sub New(handler As Action(Of T))  
    Protected Overridable Sub OnReport(value As T)  
    Public Event ProgressChanged As EventHandler(Of T>  
End Class  

Progress<T>의 인스턴스는 비동기 작업이 진행률 업데이트를 보고할 때마다 발생하는 ProgressChanged 이벤트를 노출합니다.An instance of Progress<T> exposes a ProgressChanged event, which is raised every time the asynchronous operation reports a progress update. ProgressChanged 이벤트는 SynchronizationContext 인스턴스를 인스턴스화할 때 캡처된 Progress<T> 개체에서 발생합니다.The ProgressChanged event is raised on the SynchronizationContext object that was captured when the Progress<T> instance was instantiated. 동기화 컨텍스트를 사용할 수 없는 경우 스레드 풀을 대상으로 하는 기본 컨텍스트가 사용됩니다.If no synchronization context was available, a default context that targets the thread pool is used. 처리기가 이 이벤트에 등록될 수 있습니다.Handlers may be registered with this event. 또한 편의를 위해 단일 처리기가 Progress<T> 생성자에 제공될 수 있으며 ProgressChanged 이벤트의 이벤트 처리기와 같이 동작합니다.A single handler may also be provided to the Progress<T> constructor for convenience, and behaves just like an event handler for the ProgressChanged event. 진행률 업데이트는 이벤트 처리기를 실행하는 동안 비동기 작업이 지연되지 않도록 비동기적으로 발생합니다.Progress updates are raised asynchronously to avoid delaying the asynchronous operation while event handlers are executing. 다른 IProgress<T> 구현에서 다른 의미 체계를 적용하도록 선택할 수 있습니다.Another IProgress<T> implementation could choose to apply different semantics.

제공할 오버로드 선택Choosing the overloads to provide

TAP 구현에서 선택적 CancellationToken과 선택적 IProgress<T> 매개 변수를 모두 사용하는 경우 잠재적으로 최대 4개의 오버로드가 필요할 수 있습니다.If a TAP implementation uses both the optional CancellationToken and optional IProgress<T> parameters, it could potentially require up to four overloads:

public Task MethodNameAsync(…);  
public Task MethodNameAsync(…, CancellationToken cancellationToken);  
public Task MethodNameAsync(…, IProgress<T> progress);   
public Task MethodNameAsync(…,   
    CancellationToken cancellationToken, IProgress<T> progress);  
Public MethodNameAsync(…) As Task  
Public MethodNameAsync(…, cancellationToken As CancellationToken cancellationToken) As Task  
Public MethodNameAsync(…, progress As IProgress(Of T)) As Task   
Public MethodNameAsync(…, cancellationToken As CancellationToken,   
                       progress As IProgress(Of T)) As Task  

그러나 많은 TAP 구현에서 취소 또는 진행률 기능을 제공하지 않으므로 단일 방법이 필요합니다.However, many TAP implementations provide neither cancellation or progress capabilities, so they require a single method:

public Task MethodNameAsync(…);  
Public MethodNameAsync(…) As Task  

TAP 구현에서 취소 또는 진행률을 지원하지만 둘 모두 지원하지 않는 경우 두 가지 오버로드를 제공할 수 있습니다.If a TAP implementation supports either cancellation or progress but not both, it may provide two overloads:

public Task MethodNameAsync(…);  
public Task MethodNameAsync(…, CancellationToken cancellationToken);  
  
// … or …  
  
public Task MethodNameAsync(…);  
public Task MethodNameAsync(…, IProgress<T> progress);  
Public MethodNameAsync(…) As Task  
Public MethodNameAsync(…, cancellationToken As CancellationToken) As Task  
  
' … or …  
  
Public MethodNameAsync(…) As Task  
Public MethodNameAsync(…, progress As IProgress(Of T)) As Task  

TAP 구현에서 취소와 진행률을 모두 지원하는 경우 4가지 오버로드를 모두 노출할 수 있습니다.If a TAP implementation supports both cancellation and progress, it may expose all four overloads. 그러나 다음 두 가지만 제공할 수 있습니다.However, it may provide only the following two:

public Task MethodNameAsync(…);  
public Task MethodNameAsync(…,   
    CancellationToken cancellationToken, IProgress<T> progress);  
Public MethodNameAsync(…) As Task  
Public MethodNameAsync(…, cancellationToken As CancellationToken,   
                       progress As IProgress(Of T)) As Task  

누락된 두 개의 중간 조합을 조정하기 위해 개발자가 None 매개 변수에 대해 CancellationToken 또는 기본값인 cancellationToken을 전달하고 null 매개 변수에 대해 progress을 전달할 수 있습니다.To compensate for the two missing intermediate combinations, developers may pass None or a default CancellationToken for the cancellationToken parameter and null for the progress parameter.

TAP 메서드를 사용할 때마다 취소 또는 진행률을 이용해야 하는 경우 관련 매개 변수를 허용하지 않는 오버로드는 생략할 수 있습니다.If you expect every usage of the TAP method to support cancellation or progress, you may omit the overloads that don’t accept the relevant parameter.

여러 오버로드가 취소 또는 진행률을 선택하도록 노출되는 경우 취소 또는 진행률을 지원하지 않는 오버로드는 이를 지원하는 오버로드에 대해 취소의 경우 None 및 진행률의 경우 null이 전달된 것처럼 동작해야 합니다.If you decide to expose multiple overloads to make cancellation or progress optional, the overloads that don’t support cancellation or progress should behave as if they passed None for cancellation or null for progress to the overload that does support these.

제목Title 설명Description
비동기 프로그래밍 패턴Asynchronous Programming Patterns 작업 기반 비동기 패턴(TAP), 비동기 프로그래밍 모델(APM) 및 이벤트 기반 비동기 패턴(EAP)과 같이 비동기 작업을 수행하는 세 가지 패턴이 도입됩니다.Introduces the three patterns for performing asynchronous operations: the Task-based Asynchronous Pattern (TAP), the Asynchronous Programming Model (APM), and the Event-based Asynchronous Pattern (EAP).
작업 기반 비동기 패턴 구현Implementing the Task-based Asynchronous Pattern Visual Studio의 C#와 Visual Basic 컴파일러를 수동으로 사용하거나 컴파일러 및 수동적인 방법의 조합을 사용하는 이 세 가지 방법으로 작업 기반 비동기 패턴(TAP)을 구현하는 방법에 대해 설명합니다.Describes how to implement the Task-based Asynchronous Pattern (TAP) in three ways: by using the C# and Visual Basic compilers in Visual Studio, manually, or through a combination of the compiler and manual methods.
Consuming the Task-based Asynchronous PatternConsuming the Task-based Asynchronous Pattern 작업과 콜백을 사용하여 차단되지 않고 대기하는 방법에 대해 설명합니다.Describes how you can use tasks and callbacks to achieve waiting without blocking.
다른 비동기 패턴 및 형식과의 InteropInterop with Other Asynchronous Patterns and Types 비동기 프로그래밍 모델(APM) 및 이벤트 기반 비동기 패턴(EAP)을 구현하기 위해 작업 기반 비동기 패턴(TAP)을 사용하는 방법에 대해 설명합니다.Describes how to use the Task-based Asynchronous Pattern (TAP) to implement the Asynchronous Programming Model (APM) and Event-based Asynchronous Pattern (EAP).