c# – 以下Func>异步委托方法之间有什么区别?
如果我有以下方法:
public async Task<T> DoSomethingAsync<T>(Func<Task<T>> action) { // bunch of async code..then "await action()" } 以下两种用法有什么区别: public async Task MethodOneAsync() { return await DoSomethingAsync(async () => await SomeActionAsync()); } public async Task MethodTwoAsync() { return await DoSomethingAsync(() => SomeActionAsync()); } 两个编译..都工作..没有R#警告…… 有什么区别(如果有的话)?如果调用者等待,两个方法是否都会运行async? 解决方法
简答
MethodOneAsync()是真正的异步,应该使用,但MethodTwoAsync()不是真正的异步,因为它调用线程池线程 答案很长 出于测试和运行的目的,我已经简化了您的代码,如下所示: 从Linqpad的Main方法执行如下: var resultTask = MethodOneAsync(); // Comment one the methods resultTask.Result.Dump(); 实际代码 public async Task<int> DoSomethingAsync(Func<Task<int>> action) { return await Task.FromResult<int>(3); } public async Task<int> MethodOneAsync() { await Task.Delay(10); return await DoSomethingAsync(async () => await Task.FromResult<int>(3)); } public async Task<int> MethodOneAsync() { await Task.Delay(10); return await DoSomethingAsync(() => Task.FromResult<int>(3)); } 现在我回顾了两次调用之间生成的IL,以下是最重要的区别: 在DoSomethingAsync中使用Async和Await进行的第一次调用具有以下IL: <>c.<MethodOneAsync>b__2_0: IL_0000: newobj UserQuery+<>c+<<MethodOneAsync>b__2_0>d..ctor IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: ldarg.0 IL_0008: stfld UserQuery+<>c+<<MethodOneAsync>b__2_0>d.<>4__this IL_000D: ldloc.0 IL_000E: call System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.Create IL_0013: stfld UserQuery+<>c+<<MethodOneAsync>b__2_0>d.<>t__builder IL_0018: ldloc.0 IL_0019: ldc.i4.m1 IL_001A: stfld UserQuery+<>c+<<MethodOneAsync>b__2_0>d.<>1__state IL_001F: ldloc.0 IL_0020: ldfld UserQuery+<>c+<<MethodOneAsync>b__2_0>d.<>t__builder IL_0025: stloc.1 IL_0026: ldloca.s 01 IL_0028: ldloca.s 00 IL_002A: call System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.Start<<<MethodOneAsync>b__2_0>d> IL_002F: ldloc.0 IL_0030: ldflda UserQuery+<>c+<<MethodOneAsync>b__2_0>d.<>t__builder IL_0035: call System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.get_Task IL_003A: ret 没有Async和Await的第二个代码如下: <>c.<MethodOneAsync>b__2_0: IL_0000: ldc.i4.3 IL_0001: call System.Threading.Tasks.Task.FromResult<Int32> IL_0006: ret 除此之外,第一个具有完整的状态机代码,用于额外的异步等待调用,这是预期的. 重点: >对于异步方法调用,请使用async()=>等待SomeActionAsync(),因为这是真正的异步执行并适用于IO完成端口 如果需要了解差异,我可以粘贴完整的IL,但最好是在Visual Studio或LinqPad中进行评估,以了解细微差别 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |