VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • C#教程之C#异步的世界【下】(2)

, http = http, url = url, time = time, _builder = AsyncTaskMethodBuilder<string>.Create(), _state = -1 }; stateMachine._builder.Start(ref stateMachine); return stateMachine._builder.Task; }
复制代码

方法签名完全一致,只是里面的内容变成了一个状态机 GetUrlStringAsyncdStateMachine  的调用。此状态机就是编译器自动创建的。下面来看看神秘的状态机是什么鬼:

复制代码
private sealed class GetUrlStringAsyncdStateMachine : IAsyncStateMachine
{
    public int _state;
    public MyAsyncTest _this;
    private string _str1;
    public AsyncTaskMethodBuilder<string> _builder;
    private TaskAwaiter taskAwaiter1;
    private TaskAwaiter<string> taskAwaiter2;

    //异步方法的三个形参都到这里来了
    public HttpClient http;
    public int time;
    public string url;

    private void MoveNext()
    {
        string str;
        int num = this._state;
        try
        {
            TaskAwaiter awaiter;
            MyAsyncTest.GetUrlStringAsyncdStateMachine d__;
            string str2;
            switch (num)
            {
                case 0:
                    break;

                case 1:
                    goto Label_00CD;

                default:
                    //这里是异步方法 await Task.Delay(time);的具体实现
                    awaiter = Task.Delay(this.time).GetAwaiter();
                    if (awaiter.IsCompleted)
                    {
                        goto Label_0077;
                    }
                    this._state = num = 0;
                    this.taskAwaiter1 = awaiter;
                    d__ = this;
                    this._builder.AwaitUnsafeOnCompleted<TaskAwaiter, MyAsyncTest.GetUrlStringAsyncdStateMachine>(ref awaiter, ref d__);
                    return;
            }
            awaiter = this.taskAwaiter1;
            this.taskAwaiter1 = new TaskAwaiter();
            this._state = num = -1;
        Label_0077:
            awaiter.GetResult();
            awaiter = new TaskAwaiter();
            //这里是异步方法await http.GetStringAsync(url);的具体实现
            TaskAwaiter<string> awaiter2 = this.http.GetStringAsync(this.url).GetAwaiter();
            if (awaiter2.IsCompleted)
            {
                goto Label_00EA;
            }
            this._state = num = 1;
            this.taskAwaiter2 = awaiter2;
            d__ = this;
            this._builder.AwaitUnsafeOnCompleted<TaskAwaiter<string>, MyAsyncTest.GetUrlStringAsyncdStateMachine>(ref awaiter2, ref d__);
            return;
        Label_00CD:
            awaiter2 = this.taskAwaiter2;
            this.taskAwaiter2 = new TaskAwaiter<string>();
            this._state = num = -1;
        Label_00EA:
            str2 = awaiter2.GetResult();
            awaiter2 = new TaskAwaiter<string>();
            this._str1 = str2;
            str = this._str1;
        }
        catch (Exception exception)
        {
            this._state = -2;
            this._builder.SetException(exception);
            return;
        }
        this._state = -2;
        this._builder.SetResult(str);
    }

    [DebuggerHidden]
    private void SetStateMachine(IAsyncStateMachine stateMachine)
    {
    }

}
复制代码

明显多个异步等待执行的时候就是在不断调用状态机中的MoveNext()方法。经验来至我们之前分析过的IEumerable,不过今天的这个明显复杂度要高于以前的那个。猜测是如此,我们还是来验证下事实:

在起始方法 GetUrlStringAsync 第一次启动状态机 stateMachine._builder.Start(ref stateMachine);

 确实是调用了 MoveNext 。因为_state的初始值是-1,所以执行到了下面的位置:

绕了一圈又回到了 MoveNext 。由此,我们可以现象成多个异步调用就是在不断执行MoveNext直到结束。

说了这么久有什么意思呢,似乎忘记了我们的目的是要通过之前编写的测试代码来分析异步的执行逻辑的。

再次贴出之前的测试代码,以免忘记了。

反编译后代码执行逻辑图:

当然这只是可能性较大的执行流程,但也有 awaiter.Iscompleted 为 true 的情况。其他可能的留着大家自己去琢磨吧。 

 

本文已同步至索引目录:《C#基础知识巩固》

本文demo:https://github.com/zhaopeiym/BlogDemoCode



相关教程
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号