2017-02-08 2 views
1

Скажем, у нас есть два следующих метода внутри стандартного контроллера mvc.MVC async controller Действия

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

Как запросы обрабатываются пул потоков

На веб-сервере, .NET Framework поддерживает пул потоков, которые используются для обслуживания запросов ASP.NET. Когда запрос поступает, поток из пула отправляется для обработки этого запроса. Если запрос обрабатывается синхронно, поток, который обрабатывает запрос, занят во время обработки запроса, и этот поток не может обслуживать другой запрос.

Моя цель - понять, следует ли сопровождать метод, возвращающий задачу, со словом async. Если ключевое слово отсутствует, оно будет рассматривать метод как синхронный и удерживать поток, хотя SomeAsyncMethod имеет await, в котором создается обратный вызов?

+0

С 'async/await' он будет обслуживать ваши запрос, возврат в threadpool для обслуживания других запросов и возобновление действия при завершении операции async. Это означает, что вы можете делать другие вещи после 'async'. Это также означает, что если операция 'async' не удалась, вы можете получить' Exception'.Со вторым, где вы вернете «Задачу», это будет огонь и забудьте действие. Это означает, что вы в основном не заботитесь о результате операции «async». – 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

Смежные вопросы