C# “之间有什么区别吗?”;等待任务。运行();返回&引用;及;返回任务。运行();?

C# “之间有什么区别吗?”;等待任务。运行();返回&引用;及;返回任务。运行();?,c#,async-await,C#,Async Await,以下两段代码在概念上是否存在差异: async Task TestAsync() { await Task.Run(() => DoSomeWork()); } 及 Task TestAsync() { return Task.Delay(1000); } 生成的代码是否也不同 编辑:以避免与任务混淆。运行,类似情况: async Task TestAsync() { await Task.Delay(1000); } 及 Task TestAsync(

以下两段代码在概念上是否存在差异:

async Task TestAsync() 
{
    await Task.Run(() => DoSomeWork());
}

Task TestAsync() 
{
    return Task.Delay(1000);
}
生成的代码是否也不同

编辑:以避免与
任务混淆。运行
,类似情况:

async Task TestAsync() 
{
    await Task.Delay(1000);
}

Task TestAsync() 
{
    return Task.Delay(1000);
}
最新更新:除了公认的答案之外,处理
LocalCallContext
的方式也有所不同:

这两个示例确实不同。当一个方法被标记为
async
关键字时,编译器会在后台生成一个状态机。这就是在等待一个可等待的事件被等待之后,负责恢复延续的原因

相反,当一个方法没有标记为
async
时,您就失去了
wait
waitables的功能。(也就是说,在方法本身内部;调用方仍然可以等待该方法。)但是,通过避免使用
async
关键字,您不再生成状态机,这可能会增加相当多的开销(将局部变量提升到状态机的字段,将其他对象提升到GC)

在这样的示例中,如果您能够避免
async wait
并直接返回一个waitable,那么应该这样做以提高方法的效率

请看和,它们与您的问题和此答案非常相似

  • 第一个方法甚至不编译

    由于“
    Program.TestAsync()
    ”是一个返回“
    Task
    ”的异步方法,因此返回关键字后面不能跟有对象表达式。您是否打算返回“
    任务”

    一定是这样

    async Task TestAsync()
    {
        await Task.Run(() => DoSomeWork());
    }
    
  • 这两者在概念上存在重大差异。第一个是异步的,第二个不是。要了解有关
    async
    /
    内部的更多信息,请等待

  • 它们确实生成不同的代码

    .method private hidebysig 
        instance class [mscorlib]System.Threading.Tasks.Task TestAsync () cil managed 
    {
        .custom instance void [mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [mscorlib]System.Type) = (
            01 00 25 53 4f 54 65 73 74 50 72 6f 6a 65 63 74
            2e 50 72 6f 67 72 61 6d 2b 3c 54 65 73 74 41 73
            79 6e 63 3e 64 5f 5f 31 00 00
        )
        .custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x216c
        // Code size 62 (0x3e)
        .maxstack 2
        .locals init (
            [0] valuetype SOTestProject.Program/'<TestAsync>d__1',
            [1] class [mscorlib]System.Threading.Tasks.Task,
            [2] valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder
        )
    
        IL_0000: ldloca.s 0
        IL_0002: ldarg.0
        IL_0003: stfld class SOTestProject.Program SOTestProject.Program/'<TestAsync>d__1'::'<>4__this'
        IL_0008: ldloca.s 0
        IL_000a: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Create()
        IL_000f: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder SOTestProject.Program/'<TestAsync>d__1'::'<>t__builder'
        IL_0014: ldloca.s 0
        IL_0016: ldc.i4.m1
        IL_0017: stfld int32 SOTestProject.Program/'<TestAsync>d__1'::'<>1__state'
        IL_001c: ldloca.s 0
        IL_001e: ldfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder SOTestProject.Program/'<TestAsync>d__1'::'<>t__builder'
        IL_0023: stloc.2
        IL_0024: ldloca.s 2
        IL_0026: ldloca.s 0
        IL_0028: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Start<valuetype SOTestProject.Program/'<TestAsync>d__1'>(!!0&)
        IL_002d: ldloca.s 0
        IL_002f: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder SOTestProject.Program/'<TestAsync>d__1'::'<>t__builder'
        IL_0034: call instance class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::get_Task()
        IL_0039: stloc.1
        IL_003a: br.s IL_003c
    
        IL_003c: ldloc.1
        IL_003d: ret
    } // end of method Program::TestAsync
    
    .method私有隐藏
    实例类[mscorlib]System.Threading.Tasks.Task TestAsync()cil托管
    {
    .custom instance void[mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(类[mscorlib]System.Type)=(
    01 00 25 53 4f 54 65 73 74 50 72 6f 6a 65 63 74
    2e 50 72 6f 67 72 61 6d 2b 3c 54 65 73 74 41 73
    79 6e 63 3e 64 5f 5f 31 00 00
    )
    .custom instance void[mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor()=(
    01 00 00 00
    )
    //方法从RVA 0x216c开始
    //代码大小62(0x3e)
    .maxstack 2
    .init(
    [0]valuetype SOTestProject.Program/'d___1',
    [1] 类[mscorlib]System.Threading.Tasks.Task,
    [2] valuetype[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder
    )
    IL_0000:ldloca.s 0
    IL_0002:ldarg.0
    IL_0003:stfld类SOTestProject.Program SOTestProject.Program/'d__1'::'4_this'
    IL_0008:ldloca.s 0
    IL_000a:调用valuetype[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Create()
    IL_000f:stfld valuetype[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder SOTestProject.Program/'d_1':'t_builder'
    IL_0014:ldloca.s 0
    IL_0016:ldc.i4.m1
    IL_0017:stfld int32 SOTestProject.Program/'d__1'::'1__状态'
    IL_001c:ldloca.s 0
    IL_001e:ldfld valuetype[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder SOTestProject.Program/'d_1':'t_builder'
    IL_0023:stloc.2
    IL_0024:ldloca.s 2
    IL_0026:ldloca.s 0
    IL_0028:调用实例void[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Start(!!0&)
    IL_002d:ldloca.s 0
    IL_002f:ldflda valuetype[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder SOTestProject.Program/'d_1':'t_builder'
    IL_0034:调用实例类[mscorlib]System.Threading.Tasks.Task[mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::get_Task()
    IL_0039:stloc.1
    IL_003a:br.s IL_003c
    IL_003c:ldloc.1
    IL_003d:ret
    }//方法结束程序::TestAsync
    

    Task TestAsync() 
    {
        return Task.Delay(1000);
    }
    
    .method私有隐藏
    实例类[mscorlib]System.Threading.Tasks.Task TestAsync2()cil托管
    {
    //方法从RVA 0x21d8开始
    //代码大小23(0x17)
    .maxstack 2
    .init(
    [0]类[mscorlib]System.Threading.Tasks.Task CS$1$0000
    )
    IL_0000:没有
    IL_0001:ldarg.0
    IL_0002:ldftn实例类[mscorlib]System.Threading.Tasks.Task SOTestProject.程序::'b_4'()
    IL_0008:newobj实例无效类[mscorlib]System.Func`1::.ctor(对象,本机int)
    IL_000d:调用类[mscorlib]System.Threading.Tasks.Task[mscorlib]System.Threading.Tasks.Task::Run(类[mscorlib]System.Func`1)
    IL_0012:stloc.0
    IL_0013:br.s IL_0015
    IL_0015:ldloc.0
    IL_0016:ret
    }//方法结束程序::TestAsync2
    
  • 两者的区别是什么

    async Task TestAsync() 
    {
        await Task.Delay(1000);
    }
    

    Task TestAsync() 
    {
        return Task.Delay(1000);
    }
    
    ?

    我被这个问题弄糊涂了。让我用另一个问题回答你的问题来澄清一下。两者之间有什么区别

    Func<int> MakeFunction()
    {
        Func<int> f = ()=>1;
        return ()=>f();
    }
    
    Func MakeFunction()
    {
    Func f=()=>1;
    return()=>f();
    }
    

    Task TestAsync() 
    {
        return Task.Delay(1000);
    }
    
    Func MakeFunction()
    {
    返回()=>1;
    }
    
    ?


    无论我的两件事之间有什么区别,你的两件事之间也有同样的区别。

    一个主要区别在于异常传播。异常,在
    异步任务
    方法中抛出,获取存储在返回的
    Task
    对象中,并保持休眠状态,直到通过
    await Task
    Task.Wait()
    Task.Result
    Task.GetAwaiter().GetResult()
    观察到该任务。即使从
    async
    方法的同步部分抛出,它也是以这种方式传播的

    考虑以下代码,其中
    OneTestAsync
    AnotherTestAsync
    static async Task OneTestAsync(int n)
    {
        await Task.Delay(n);
    }
    
    static Task AnotherTestAsync(int n)
    {
        return Task.Delay(n);
    }
    
    // call DoTestAsync with either OneTestAsync or AnotherTestAsync as whatTest
    static void DoTestAsync(Func<int, Task> whatTest, int n)
    {
        Task task = null;
        try
        {
            // start the task
            task = whatTest(n);
    
            // do some other stuff, 
            // while the task is pending
            Console.Write("Press enter to continue");
            Console.ReadLine();
            task.Wait();
        }
        catch (Exception ex)
        {
            Console.Write("Error: " + ex.Message);
        }
    }
    
    Press enter to continue Error: One or more errors occurred.await Task.Delay Error: 2nd Error: The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer. Parameter name: millisecondsDelayError: 1st
    // async
    async Task<int> MethodAsync(int arg)
    {
        if (arg < 0)
            throw new ArgumentException("arg");
        // ...
        return 42 + arg;
    }
    
    // non-async
    Task<int> MethodAsync(int arg)
    {
        var task = new Task<int>(() => 
        {
            if (arg < 0)
                throw new ArgumentException("arg");
            // ...
            return 42 + arg;
        });
    
        task.RunSynchronously(TaskScheduler.Default);
        return task;
    }
    
    static async Task TestAsync()
    {
        await Task.Delay(1000);
    }
    
    void Form_Load(object sender, EventArgs e)
    {
        TestAsync().Wait(); // dead-lock here
    }
    
    Task TestAsync() 
    {
        return Task.Delay(1000);
    }