加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 以下Func>异步委托方法之间有什么区别?

发布时间:2020-12-15 07:41:46 所属栏目:百科 来源:网络整理
导读:如果我有以下方法: public async TaskT DoSomethingAsyncT(FuncTaskT action){ // bunch of async code..then "await action()"} 以下两种用法有什么区别: public async Task MethodOneAsync(){ return await DoSomethingAsync(async () = await SomeActio
如果我有以下方法:
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完成端口
>在其他情况下,它为异步方法执行调用Threadpool线程,这对异步执行不利

如果需要了解差异,我可以粘贴完整的IL,但最好是在Visual Studio或LinqPad中进行评估,以了解细微差别

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读