简体   繁体   English

传播的异步/等待方法调用

[英]Propagated Async/Await Method Calls

So I have this method in my base controller: 所以我在我的基本控制器中有这个方法:

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);
}

I want to use it like this: 我想这样使用它:

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);
}

So what I'm passing through to ExecuteSimpleQuery is an awaitable method LoginAsync , I just want to make sure I'm properly awaiting the method. 所以我传递给ExecuteSimpleQuery是一个awaitable方法LoginAsync ,我只是想确保我正在等待该方法。

My thought process is: 我的思考过程是:

  1. LoginAsync returns a Task<bool> therefore the Func has to return that. LoginAsync返回一个Task<bool>因此Func必须返回它。
  2. When passing it, you can await it, so do. 通过它时,你可以await它,也可以。
  3. Because the Func returns a Task<bool> inside ExecuteSimpleQuery you can await it there, so should 因为FuncExecuteSimpleQuery返回一个Task<bool> ,你可以await那里await
  4. ExecuteSimpleQuery is awaiting a method, therefore has to have the async keyword and therefore has to return Task<T> . ExecuteSimpleQuery正在等待一个方法,因此必须具有async关键字,因此必须返回Task<T>
  5. The last point propagates to the Login action, that method returns Task<T> so it can be awaited, so should. 最后一点传播到Login操作,该方法返回Task<T>因此可以等待它。

Am I even close? 我甚至关闭了吗?

This will work. 这会奏效。 It can be simplified a little bit: 它可以简化一点:

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

could be written as 可写成

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

because LoginAsync already returns a Task . 因为LoginAsync已经返回一个Task That said always awaiting tasks whenever you process them has a certain consistency to it. 这就是说,每当你处理任务时总是在等待它们具有一定的一致性。 It isn't really harmful to wrap this task the way you did. 以你的方式包装这个任务并不是真的有害。 I think both ways are reasonable. 我认为两种方式都是合理的。

If LoginAsync can not throw any exception (that you care about) you don't need the lambda at all. 如果LoginAsync不能抛出任何异常(您关心的话),则根本不需要lambda。 Exceptions are usually stored in the Task when you call an async method. 调用异步方法时,异常通常存储在Task You could directly pass a Task to ExecuteSimpleQuery . 您可以直接将Task传递给ExecuteSimpleQuery If LoginAsync does not adhere to this pattern you cannot do this because the exception would be triggered too early. 如果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)
    {
        //...
    }

    //...
}

You can test this by saying: 您可以通过以下方式测试:

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

The catch will be hit. catch将被击中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM