我们提供安全,免费的手游软件下载!
await
实现原理详解
在C#中,
async
和
await
关键字用于编写异步代码。本文将详细介绍
await
的实现原理,包括状态机的生成、回调函数的注册和触发等关键步骤。
在C#中,
async
关键字标记一个方法为异步方法,而
await
关键字用于等待一个异步操作完成。异步方法可以提高程序的响应性和性能,特别是在处理I/O操作和网络请求时。
我们以一个简单的异步方法为例,来详细解释
await
的实现原理。
public class Example
{
public async Task CalculateAsync()
{
int a = await Task.Run(() => 10);
int b = await Task.Run(() => 20);
return a + b;
}
}
编译器会为每个异步方法生成一个状态机。状态机是一个结构体,包含了异步方法的所有局部变量和状态信息。
public class Example
{
public Task CalculateAsync()
{
d__0 stateMachine = new d__0();
stateMachine.<>4__this = this;
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[StructLayout(LayoutKind.Auto)]
[AsyncMethodBuilder(typeof(AsyncTaskMethodBuilder))]
private struct d__0 : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
public Example <>4__this;
public int 5__1;
public TaskAwaiter <>u__1;
private void MoveNext()
{
int num = <>1__state;
try
{
TaskAwaiter awaiter;
switch (num)
{
case 0:
goto TR_0000;
case 1:
<>1__state = -1;
awaiter = <>u__1;
<>u__1 = default(TaskAwaiter);
goto TR_0001;
case 2:
<>1__state = -1;
break;
default:
<>1__state = 0;
awaiter = Task.Run(() => 10).GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
return;
}
goto TR_0000;
}
TR_0000:
5__1 = awaiter.GetResult();
awaiter = Task.Run(() => 20).GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 1);
<>u__1 = awaiter;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
return;
}
TR_0001:
int b = awaiter.GetResult();
int result = 5__1 + b;
<>1__state = -2;
<>t__builder.SetResult(result);
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
}
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
}
}
}
在
CalculateAsync
方法中,创建状态机实例
。
d__0 stateMachine = new d__0();
stateMachine.<>4__this = this;
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
<>4__this
:指向当前实例,即
Example
类的实例。
<>t__builder
:创建
AsyncTaskMethodBuilder
实例,用于管理任务的生命周期。
<>1__state
:初始化状态为
-1
,表示方法尚未开始执行。
调用
Start
方法开始执行异步方法。
Start
方法会调用状态机的
MoveNext
方法。
stateMachine.<>t__builder.Start(ref stateMachine);
在
MoveNext
方法中,根据当前状态
<>1__state
执行相应的代码。
private void MoveNext()
{
int num = <>1__state;
try
{
TaskAwaiter awaiter;
switch (num)
{
// 处理不同的状态
}
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
}
}
await
遇到第一个
await
关键字时,调用
Task.Run(() => 10).GetAwaiter()
获取
Awaiter
对象。
awaiter = Task.Run(() => 10).GetAwaiter();
awaiter.IsCompleted
,如果任务已经完成,直接调用
awaiter.GetResult()
获取结果。
<>1__state
,保存
awaiter
对象,并调用
<>t__builder.AwaitUnsafeOnCompleted
注册回调。
if (!awaiter.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
return;
}
AwaitUnsafeOnCompleted
方法会注册一个回调,当任务完成时,回调会被触发。
public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.UnsafeOnCompleted(stateMachine.MoveNext);
}
awaiter.UnsafeOnCompleted
方法注册一个回调函数,该回调函数会在任务完成时被触发。
stateMachine.MoveNext
是一个委托,指向状态机的
MoveNext
方法。
当任务完成时,回调会被触发,重新调用
MoveNext
方法,恢复异步方法的执行。
public void OnCompleted(Action continuation)
{
task.ContinueWith(_ => continuation(), TaskScheduler.Default);
}
从上次暂停的地方继续执行方法体。
TR_0000:
5__1 = awaiter.GetResult();
awaiter = Task.Run(() => 20).GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 1);
<>u__1 = awaiter;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
return;
}
await
关键字时,重复上述步骤。
当所有异步操作完成并计算出结果后,设置状态
<>1__state
为
-2
,表示方法已经完成。
int b = awaiter.GetResult();
int result = 5__1 + b;
<>1__state = -2;
<>t__builder.SetResult(result);
<>t__builder.SetResult
设置任务的结果。
<>t__builder.SetException
设置任务的异常。
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
}
AsyncTaskMethodBuilder
AsyncTaskMethodBuilder
是一个辅助类,用于构建和管理异步方法的任务。它提供了以下方法:
Create
:创建一个新的
AsyncTaskMethodBuilder
实例。
Start
:开始执行异步方法,调用状态机的
MoveNext
方法。
AwaitUnsafeOnCompleted
:注册回调函数,当任务完成时触发回调。
SetResult
:设置任务的结果。
SetException
:设置任务的异常。
AsyncTaskMethodBuilder
的内部实现
AsyncTaskMethodBuilder
内部维护了一个
Task
对象,用于表示异步操作的结果。当异步方法完成时,
SetResult
方法会设置任务的结果,
SetException
方法会设置任务的异常。
public struct AsyncTaskMethodBuilder
{
private Task task;
public static AsyncTaskMethodBuilder Create()
{
return new AsyncTaskMethodBuilder(new Task());
}
private AsyncTaskMethodBuilder(Task task)
{
this.task = task;
}
public void Start(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
}
public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.UnsafeOnCompleted(stateMachine.MoveNext);
}
public void SetResult(TResult result)
{
task.SetResult(result);
}
public void SetException(Exception exception)
{
task.SetException(exception);
}
public Task Task => task;
}
异步方法的生命周期可以分为以下几个阶段:
Start
方法开始执行异步方法。
MoveNext
方法中,根据当前状态执行相应的代码。
await
:检查任务是否完成,如果未完成则注册回调并暂停方法执行。
MoveNext
方法,恢复异步方法的执行。
使用
async
和
await
编写的异步方法有以下优势:
尽管
async
和
await
提供了许多优势,但在使用时也需要注意以下几点:
async void
:
async void
方法主要用于事件处理程序,其他情况下应避免使用,因为它无法被等待,并且异常处理较为困难。
AggregateException
中,需要特殊处理。
using
语句时,需要注意
Dispose
方法的调用时机。
为了更好地理解这个过程,可以用流程图来展示:
通过上述详细的解释和示例代码,我们可以总结出以下几点:
async
和
await
关键字用于编写异步代码。
MoveNext
方法的执行
:
MoveNext
方法是状态机的核心,负责管理和执行异步操作。
await
关键字时,编译器会生成代码来检查任务是否已经完成。
MoveNext
方法,从而恢复异步方法的执行。
AwaitUnsafeOnCompleted
方法的作用
:在任务完成时注册一个回调函数,回调函数会在任务完成后被触发,从而恢复异步方法的执行。
await
实现原理。如果你还有任何疑问,请随时提问!
希望这篇文章对你有所帮助!如果你有任何进一步的问题或需要更多的细节,请告诉我。
相关资讯
热门资讯