Асинхронный шаблон, основанный на задачах (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 требуется метод Begin и End.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 после имени операции используется суффикс Async — для методов, возвращающих типы с поддержкой ожидания, например Task, Task<TResult>, ValueTask и ValueTask<TResult>.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>. Синхронные операции Get, возвращающие Task<String>, могут называться GetAsync.For example, an asynchronous Get operation that returns a Task<String> can be named GetAsync. Если вы добавляете к классу, который уже содержит имя метода EAP с суффиксом Async, метод 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. Если метод запускает асинхронную операцию, но не возвращает ожидаемый тип, его имя должно начинаться с 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 возвращает System.Threading.Tasks.Task или System.Threading.Tasks.Task<TResult> в зависимости от того, возвращает ли соответствующий синхронный метод значение void или тип 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. Однако параметры out и ref исключены из этого правила, их следует избегать полностью.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. Попробуйте добавить параметр CancellationToken, даже если в аналогичном синхронном методе TAP этот параметр не применяется.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. К таким методам относятся WhenAll и WhenAny, которые рассматриваются в разделе Использование внутренних блоков объединения задач статьи Использование асинхронного шаблона, основанного на задачах.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:

  • Асинхронные методы могут вызываться из потоков пользовательского интерфейса, и любые продолжительные синхронные задачи могут негативно сказаться на скорости реагирования приложения.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

Асинхронный метод должен вызывать исключение, которое должно создаваться вызовом асинхронного метода только в ответ на ошибку использования.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. Например, если передача пустой ссылки (Nothing в Visual Basic) в виде одного из аргументов метода вызывает ошибочное состояние (как правило, представляется исключением ArgumentNullException ), можно изменить вызывающий код, чтобы убедиться, что пустая ссылка никогда не передается.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. Можно выполнить рабочую нагрузку в пуле потоков, реализовать ее с помощью асинхронного ввода-вывода (без привязки к потоку в большей части выполнения операции), выполнить ее в определенном потоке (например, в потоке пользовательского интерфейса) или использовать любое количество потенциальных контекстов.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) или неявно путем поддержки языка на основе продолжений (например, await в C#, Await в Visual Basic, AwaitValue в F#).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. Для поддержки угловых случаев типов, производных от Task и Task<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 перед ее возвращением должен вызвать метод Start для объекта Task.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 могут с уверенностью допускать, что возвращаемая задача активна, и не пытаться вызвать метод Start для любого объекта Task, который возвращается из метода TAP.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; в этом случае отсутствует результат и исключение не создается.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 считается конечным состоянием для задачи, наравне с состояниями Faulted и RanToCompletion.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. Код, который блокируется во время синхронного ожидания задачи с использованием методов Wait и WaitAll также продолжает выполняться с исключением.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. Как и в случае с отменой, реализации TAP должны предоставлять параметр IProgress<T>, только если API поддерживает уведомления о ходе выполнения.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>, потенциально может потребоваться до четырех перегрузок: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 поддерживает отмену и просмотр хода выполнения, то она может предоставить все четыре перегруженные версии.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 Описывает три способа реализации асинхронной модели на основе задач (TAP): с помощью компиляторов C# и Visual Basic в Visual Studio, вручную или путем сочетания этих методов.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.
Взаимодействие с другими асинхронными шаблонами и типамиInterop with Other Asynchronous Patterns and Types Описывает, как использовать асинхронную модель на основе задач (TAP) для реализации асинхронной модели программирования (APM) и асинхронной модели на основе событий (EAP).Describes how to use the Task-based Asynchronous Pattern (TAP) to implement the Asynchronous Programming Model (APM) and Event-based Asynchronous Pattern (EAP).