2014-10-19 5 views
0

Поэтому у меня есть этот метод в моем регуляторе:Размножается Асинхронный/Await Метод вызовов

protected async Task<KeyValuePair<bool, string>> ExecuteSimpleQuery(Func<Task<bool>> service) 
{ 
    var success = false; 
    var message = string.Empty; 

    try 
    { 
     success = await service.Invoke(); 
    } 
    catch (Exception exception) 
    { 
     message = exception.Message; 
     success = false; 
    } 

    return new KeyValuePair<bool, string>(success, message); 
} 

Я хочу, чтобы использовать его как это:

public async Task<ActionResult> Login(RegisterDto register) 
{ 
    var objectStore = 
     await this.ExecuteSimpleQuery(async() => await this.securityService.LoginAsync(register.UserName, register.Password, true)); 

    if (objectStore.Key) 
    { 
     return this.RedirectToAction("Index", "Toolbox"); 
    } 

    this.TempData["error"] = objectStore.Value; 
    return this.View(register); 
} 

Так что я проходящее до ExecuteSimpleQuery это метод awaitableLoginAsync, я просто хочу убедиться, что я правильно ожидаю метод.

Мой мыслительный процесс:

  1. LoginAsync возвращает Task<bool> поэтому Func должен вернуть это.
  2. При передаче, вы можете await, так.
  3. Поскольку Func возвращает Task<bool> внутри ExecuteSimpleQuery вы можете await его там, так должен
  4. ExecuteSimpleQuery ожидает метод, поэтому должен иметь async ключевое слово и, следовательно, должен вернуть Task<T>.
  5. Последняя точка распространяется на действие Login, этот метод возвращает Task<T>, поэтому его можно ожидать, так что должно.

Я даже близко?

+0

Почему так сложно? Кому вы делегируете логин на 'ExecuteSimpleQuery'? –

+0

Использование сервисной архитектуры У меня есть действительно последовательный способ вызова службы, поэтому вместо того, чтобы писать «try ... catch» все время, я пишу его один раз и обрабатываю одно и то же каждый раз. Просто намного проще и менее утомительно –

ответ

2

Это будет работать. Это может быть упрощено немного:

async() => await this.securityService.LoginAsync(register.UserName, register.Password, true) 

может быть написана как

() => this.securityService.LoginAsync(register.UserName, register.Password, true) 

потому LoginAsync уже возвращает Task. Тем не менее, всегда ожидая задач, когда вы их обрабатываете, имеет определенную последовательность. На самом деле не так опасно обертывать эту задачу так, как вы это делали. Я думаю, что оба пути разумны.

Если LoginAsync не может создавать никаких исключений (что вам интересно), вам вообще не нужна лямбда. Исключения обычно сохраняются в Task, когда вы вызываете метод async. Вы можете напрямую передать Task в ExecuteSimpleQuery. Если LoginAsync не придерживается этого шаблона, вы не можете этого сделать, потому что исключение будет срабатывать слишком рано.

var loginTask = securityService.LoginAsync(register.UserName, register.Password, true); 
    var objectStore = await ExecuteSimpleQuery(loginTask); 

protected async Task<KeyValuePair<bool, string>> ExecuteSimpleQuery(Task<bool> service) 
{ 
    //... 

    try 
    { 
     success = await service; 
    } 
    catch (Exception exception) 
    { 
     //... 
    } 

    //... 
} 

Вы можете проверить это, говоря:

var loginTask = Task.Run(() => { throw null; }); 

catch будет удар.

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