为什么这个异步方法没有编译错误?

时间:2017-10-23 22:11:29

标签: c# async-await task task-parallel-library

也许这是因为我对编译过程中标记为async时发生的事情缺乏了解,但为什么这个方法会编译?

    public async Task<bool> Test()
    {
        return true;
    }

这里只是寻找解释,所以我可以更好地了解发生了什么。 Task会自动被包裹吗?为什么允许这种方法? (它不遵循方法签名,即返回Task<bool>)。

更新: 看来这也适用于以下参数:

    public void Main()
    {
        Input(Test);
    }

    public async Task<bool> Test()
    {
        return true;
    }

    public void Input(Func<Task<bool>> test)
    {

    }

其中,Test方法隐式返回Task

1 个答案:

答案 0 :(得分:4)

您可以查看代码的反编译版本here

using System;
public class C {
    public async System.Threading.Tasks.Task<bool> M() {
        return false;
    }
}

该方法被编译成普通的异步方法,与状态机一样,它确实会返回Task<bool>

public class C
{
    [CompilerGenerated]
    private sealed class <M>d__0 : IAsyncStateMachine
    {
        public int <>1__state;

        public AsyncTaskMethodBuilder<bool> <>t__builder;

        public C <>4__this;

        //called when you awaiting the Task
        void IAsyncStateMachine.MoveNext()
        {
            int num = this.<>1__state;
            bool result;
            try
            {
                result = false;  //the result is set
            }
            catch (Exception arg_0C_0)
            {
                Exception exception = arg_0C_0;
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult(result); 
        }

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

    [DebuggerStepThrough, AsyncStateMachine(typeof(C.<M>d__0))]
    public Task<bool> M()
    {
        // the state machine instance created
        C.<M>d__0 <M>d__ = new C.<M>d__0(); 
        <M>d__.<>4__this = this;
        <M>d__.<>t__builder = AsyncTaskMethodBuilder<bool>.Create();
        <M>d__.<>1__state = -1;
        AsyncTaskMethodBuilder<bool> <>t__builder = <M>d__.<>t__builder;
        <>t__builder.Start<C.<M>d__0>(ref <M>d__);
        return <M>d__.<>t__builder.Task;
    }
}
顺便说一句,编译器会给你一个警告,因为你的方法永远不会await

  

警告CS1998:这种异步方法缺少等待&#39;运营商并将运行   同步。考虑使用&#39; await&#39;运营商等待   非阻塞API调用,或等待Task.Run(...)&#39;做CPU限制的工作   在后台线程上。

你是绝对正确的,你可能只是返回一个完成的任务:

using System;
using System.Threading.Tasks;
public class C {
    public Task<bool> M() {
        return Task.FromResult(false); //no need to await here at all
    }

}

对上述方法进行编码的其他方式could be found here

using System;
using System.Threading.Tasks;
public class C {
    public async Task<bool> M() {
        return false;
    }

    public async Task<bool> M2(){
        return await Task.FromResult(false);
    }

    public Task<bool> M3(){
        return Task.FromResult(false);
    }
}

我希望这能为你澄清一些事情。