Типы асинхронных задач в C #Async Task Types in C#
Расширение async
для поддержки типов задач , соответствующих определенному шаблону, в дополнение к хорошо известным типам System.Threading.Tasks.Task
и System.Threading.Tasks.Task<T>
.Extend async
to support task types that match a specific pattern, in addition to the well known types System.Threading.Tasks.Task
and System.Threading.Tasks.Task<T>
.
Тип задачиTask Type
Тип задачи — class
или struct
с связанным типом построителя , идентифицированным с помощью System.Runtime.CompilerServices.AsyncMethodBuilderAttribute
.A task type is a class
or struct
with an associated builder type identified with System.Runtime.CompilerServices.AsyncMethodBuilderAttribute
.
Тип задачи может быть не универсальным, для асинхронных методов, которые не возвращают значение или универсальный, для методов, возвращающих значение.The task type may be non-generic, for async methods that do not return a value, or generic, for methods that return a value.
Для поддержки await
тип задачи должен иметь соответствующий, доступный GetAwaiter()
метод, возвращающий экземпляр типа метода ожидания (см. статью C# 7.7.7.1 awaited Expressions ).To support await
, the task type must have a corresponding, accessible GetAwaiter()
method that returns an instance of an awaiter type (see C# 7.7.7.1 Awaitable expressions ).
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
class MyTask<T>
{
public Awaiter<T> GetAwaiter();
}
class Awaiter<T> : INotifyCompletion
{
public bool IsCompleted { get; }
public T GetResult();
public void OnCompleted(Action completion);
}
Тип построителяBuilder Type
Тип построителя — class
или struct
, соответствующий определенному типу задачи.The builder type is a class
or struct
that corresponds to the specific task type.
Тип построителя может иметь не более 1 параметра типа и не должен быть вложен в универсальный тип.The builder type can have at most 1 type parameter and must not be nested in a generic type.
Тип построителя имеет следующие public
методы.The builder type has the following public
methods.
Для типов построителя , не являющихся универсальными, SetResult()
параметр не имеет параметров.For non-generic builder types , SetResult()
has no parameters.
class MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create();
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine;
public void SetStateMachine(IAsyncStateMachine stateMachine);
public void SetException(Exception exception);
public void SetResult(T result);
public void AwaitOnCompleted<TAwaiter, TStateMachine>(
ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine;
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine;
public MyTask<T> Task { get; }
}
ВыполнениеExecution
Приведенные выше типы используются компилятором для создания кода конечного автомата async
метода.The types above are used by the compiler to generate the code for the state machine of an async
method.
(Созданный код эквивалентен коду, созданному для асинхронных методов, которые возвращают Task
, Task<T>
или void
.(The generated code is equivalent to the code generated for async methods that return Task
, Task<T>
, or void
.
Разница заключается в том, что для этих хорошо известных типов типы построителя также известны компилятору.)The difference is, for those well known types, the builder types are also known to the compiler.)
Builder.Create()
вызывается для создания экземпляра типа построителя.Builder.Create()
is invoked to create an instance of the builder type.
Если конечный автомат реализуется как struct
, то builder.SetStateMachine(stateMachine)
вызывается с упакованным экземпляром конечного автомата, который построитель может кэшировать при необходимости.If the state machine is implemented as a struct
, then builder.SetStateMachine(stateMachine)
is called with a boxed instance of the state machine that the builder can cache if necessary.
builder.Start(ref stateMachine)
вызывается для связывания построителя с экземпляром конечного автомата, созданным компилятором.builder.Start(ref stateMachine)
is invoked to associate the builder with compiler-generated state machine instance.
Построитель должен вызвать stateMachine.MoveNext()
либо в, Start()
либо после, Start()
чтобы переместить конечный автомат.The builder must call stateMachine.MoveNext()
either in Start()
or after Start()
has returned to advance the state machine.
После Start()
возврата async
метод вызывает, builder.Task
чтобы задача возвращалась из асинхронного метода.After Start()
returns, the async
method calls builder.Task
for the task to return from the async method.
Каждый вызов метода stateMachine.MoveNext()
переместит конечный автомат.Each call to stateMachine.MoveNext()
will advance the state machine.
Если конечный автомат завершается успешно, builder.SetResult()
вызывается метод с возвращаемым значением метода при его наличии.If the state machine completes successfully, builder.SetResult()
is called, with the method return value if any.
При возникновении исключения в конечный автомат builder.SetException(exception)
вызывается.If an exception is thrown in the state machine, builder.SetException(exception)
is called.
Если конечный автомат достигает await expr
выражения, expr.GetAwaiter()
вызывается метод.If the state machine reaches an await expr
expression, expr.GetAwaiter()
is invoked.
Если ожидающий метод реализует ICriticalNotifyCompletion
и IsCompleted
имеет значение false, конечный автомат вызывает builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine)
.If the awaiter implements ICriticalNotifyCompletion
and IsCompleted
is false, the state machine invokes builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine)
.
AwaitUnsafeOnCompleted()
должен вызываться awaiter.OnCompleted(action)
с действием, которое вызывает, stateMachine.MoveNext()
когда завершается выполнение метода await.AwaitUnsafeOnCompleted()
should call awaiter.OnCompleted(action)
with an action that calls stateMachine.MoveNext()
when the awaiter completes. Аналогично для INotifyCompletion
и builder.AwaitOnCompleted()
.Similarly for INotifyCompletion
and builder.AwaitOnCompleted()
.
Overload ResolutionOverload Resolution
Разрешение перегрузки расширено для распознавания типов задач в дополнение к Task
и Task<T>
.Overload resolution is extended to recognize task types in addition to Task
and Task<T>
.
async
Лямбда-выражение без возвращаемого значения является точным соответствием для параметра-кандидата перегрузки неуниверсального типа задачи , а async
лямбда с возвращаемым типом T
является точным соответствием для параметра кандидата перегрузки универсального типа задачи.An async
lambda with no return value is an exact match for an overload candidate parameter of non-generic task type , and an async
lambda with return type T
is an exact match for an overload candidate parameter of generic task type.
В противном случае, если async
лямбда-выражение не является точным соответствием для одного из двух потенциальных параметров типов задач или точное совпадение для обоих, и существует неявное преобразование из одного типа кандидата в другой, от кандидата WINS.Otherwise if an async
lambda is not an exact match for either of two candidate parameters of task types , or an exact match for both, and there is an implicit conversion from one candidate type to the other, the from candidate wins. В противном случае рекурсивно вычисляют типы A
и B
в Task1<A>
и Task2<B>
для лучшего соответствия.Otherwise recursively evaluate the types A
and B
within Task1<A>
and Task2<B>
for better match.
В противном случае, если async
лямбда-выражение не является точным соответствием для одного из двух потенциальных параметров типов задач , но один кандидат является более специализированным типом, чем другой, более специализированным кандидатом является WINS.Otherwise if an async
lambda is not an exact match for either of two candidate parameters of task types , but one candidate is a more specialized type than the other, the more specialized candidate wins.