2017-02-08 185 views
1

假設我們在標準mvc控制器中有以下兩種方法。MVC異步控制器操作

public class SomeController : Controller 
{ 
    public async Task<Response> SomeAction1() 
     => await _someService.SomeAsyncMethod(); 

    public Task<Response> SomeAction2() 
     => _someService.SomeAsyncMethod(); 

    // SomeAsyncMethod might look like this. 
    // public async Task<Response> SomeAsyncMethod() 
    // => await someDbAction(); 
} 

簡單的問題:基礎控制器類是否執行任務作爲等待/異步?

或者,這兩個操作是否完全相同?

- 編輯了一下澄清。 -

https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4

如何請求由線程池

在Web服務器處理時,.NET Framework維護用於服務的ASP.NET請求的線程池。當請求到達時,將調度池中的線程來處理該請求。如果請求被同步處理,處理請求的線程處於忙碌狀態,並且該線程無法處理其他請求。

我的目標是瞭解返回Task的方法是否需要伴隨單詞async。如果關鍵字不存在,那麼它會將該方法視爲同步並保持線程,即使SomeAsyncMethod中有一個await創建回調?

+0

隨着'異步相當可觀/ await'將你的服務請求,返回到線程池以處理其他請求,並在異步操作完成時恢復您的操作。這意味着你可以在'async'之後做其他事情。這也意味着如果你的'async'操作失敗了,你可以得到'Exception's。在第二個返回「任務」的地方,這將是一場火災和遺忘的行動。這意味着你基本上不關心「異步」操作的結果。 – JohanP

回答

3

做這兩個動作做同樣的事情?

不是正好。儘管它們都具有相同的效果。當你標記方法async並在方法體的一個或多個await表達式,編譯器將生成一個狀態機的await調用後恢復方法異步。

但是,由於方法主體是一個返回Task<Action>的單一方法調用,所有該編譯器機器都是無用的,並且直接返回Task將導致較小的編譯代碼。

在運行時,你可能不會注意到有什麼差別,可能除了稍高的執行時間async Task<Action>情況。

+0

我認爲你的答案是正確的,但它不是我正在尋找的我已經更新了問題的清晰度。 – Spaceman

1

我提出使用兩個簡化的測試方法await和剛剛執行並返回Task

private static async Task<int> TestAwait() 
{ 
    await Task.Delay(1000); 
    return 0; 
} 

private static Task Test() 
{ 
    return Task.Delay(1000); 
} 

兩個生成的IL有很大的不同:

TestAwait: 
IL_0000: newobj  UserQuery+<TestAwait>d__0..ctor 
IL_0005: stloc.0  
IL_0006: ldloc.0  
IL_0007: call   System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.Create 
IL_000C: stfld  UserQuery+<TestAwait>d__0.<>t__builder 
IL_0011: ldloc.0  
IL_0012: ldc.i4.m1 
IL_0013: stfld  UserQuery+<TestAwait>d__0.<>1__state 
IL_0018: ldloc.0  
IL_0019: ldfld  UserQuery+<TestAwait>d__0.<>t__builder 
IL_001E: stloc.1  
IL_001F: ldloca.s 01 
IL_0021: ldloca.s 00 
IL_0023: call  System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.Start<<TestAwait>d__0> 
IL_0028: ldloc.0  
IL_0029: ldflda  UserQuery+<TestAwait>d__0.<>t__builder 
IL_002E: call  System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.get_Task 
IL_0033: ret 

<TestAwait>d__0.MoveNext: 
IL_0000: ldarg.0  
IL_0001: ldfld  UserQuery+<TestAwait>d__0.<>1__state 
IL_0006: stloc.0  
IL_0007: ldloc.0  
IL_0008: brfalse.s IL_000C 
IL_000A: br.s  IL_000E 
IL_000C: br.s  IL_004C 
IL_000E: nop   
IL_000F: ldc.i4  E8 03 00 00 
IL_0014: call  System.Threading.Tasks.Task.Delay 
IL_0019: callvirt System.Threading.Tasks.Task.GetAwaiter 
IL_001E: stloc.2  
IL_001F: ldloca.s 02 
IL_0021: call  System.Runtime.CompilerServices.TaskAwaiter.get_IsCompleted 
IL_0026: brtrue.s IL_0068 
IL_0028: ldarg.0  
IL_0029: ldc.i4.0  
IL_002A: dup   
IL_002B: stloc.0  
IL_002C: stfld  UserQuery+<TestAwait>d__0.<>1__state 
IL_0031: ldarg.0  
IL_0032: ldloc.2  
IL_0033: stfld  UserQuery+<TestAwait>d__0.<>u__1 
IL_0038: ldarg.0  
IL_0039: stloc.3  
IL_003A: ldarg.0  
IL_003B: ldflda  UserQuery+<TestAwait>d__0.<>t__builder 
IL_0040: ldloca.s 02 
IL_0042: ldloca.s 03 
IL_0044: call  System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.AwaitUnsafeOnCompleted<TaskAwaiter,<TestAwait>d__0> 
IL_0049: nop   
IL_004A: leave.s  IL_00AB 
IL_004C: ldarg.0  
IL_004D: ldfld  UserQuery+<TestAwait>d__0.<>u__1 
IL_0052: stloc.2  
IL_0053: ldarg.0  
IL_0054: ldflda  UserQuery+<TestAwait>d__0.<>u__1 
IL_0059: initobj  System.Runtime.CompilerServices.TaskAwaiter 
IL_005F: ldarg.0  
IL_0060: ldc.i4.m1 
IL_0061: dup   
IL_0062: stloc.0  
IL_0063: stfld  UserQuery+<TestAwait>d__0.<>1__state 
IL_0068: ldloca.s 02 
IL_006A: call  System.Runtime.CompilerServices.TaskAwaiter.GetResult 
IL_006F: nop   
IL_0070: ldloca.s 02 
IL_0072: initobj  System.Runtime.CompilerServices.TaskAwaiter 
IL_0078: ldc.i4.0  
IL_0079: stloc.1  
IL_007A: leave.s  IL_0096 
IL_007C: stloc.s  04 
IL_007E: ldarg.0  
IL_007F: ldc.i4.s FE 
IL_0081: stfld  UserQuery+<TestAwait>d__0.<>1__state 
IL_0086: ldarg.0  
IL_0087: ldflda  UserQuery+<TestAwait>d__0.<>t__builder 
IL_008C: ldloc.s  04 
IL_008E: call  System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.SetException 
IL_0093: nop   
IL_0094: leave.s  IL_00AB 
IL_0096: ldarg.0  
IL_0097: ldc.i4.s FE 
IL_0099: stfld  UserQuery+<TestAwait>d__0.<>1__state 
IL_009E: ldarg.0  
IL_009F: ldflda  UserQuery+<TestAwait>d__0.<>t__builder 
IL_00A4: ldloc.1  
IL_00A5: call  System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Int32>.SetResult 
IL_00AA: nop   
IL_00AB: ret   

<TestAwait>d__0.SetStateMachine: 
IL_0000: ret   

<TestAwait>d__0..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: nop   
IL_0007: ret   

-------------- END OF TESTAWAIT 

Test: 
IL_0000: nop   
IL_0001: ldc.i4  E8 03 00 00 
IL_0006: call  System.Threading.Tasks.Task.Delay 
IL_000B: stloc.0  
IL_000C: br.s  IL_000E 
IL_000E: ldloc.0  
IL_000F: ret 

所以代碼量編譯器生成是TestAwait

+0

這不完全是我的目標,我已經更新了這個問題。 – Spaceman