返回Task<bool>和返回bool之间有什么区别?

5

希望这是一个简单易懂的答案。

我在 ASP.NET Core 1 中使用 C# MVC Web API。我正在创建网络方法,并且已经看到了返回数据方面的示例。

示例1:

public async Task<IActionResult> ExampleCall([FromBody]ExampleObj model)
{
     // Call some lower level function...
     var result = LowerLevelCall(model);
     return result;
}

And seen other examples like this.

Example 2:

public async Task<IActionResult> ExampleCall([FromBody]ExampleObj model)
{
     // Call some lower level function...
     var result = await LowerLevelCall(model);
     return result;
}

主要的区别是示例2使用了await操作符。实现await操作符有什么影响?相比于示例1中等待代码完成,这样做是否会释放资源?
提前感谢任何建议!

2
这个怎么样?https://dev59.com/8WYq5IYBdhLWcg3wzDvk - Patrick Hofman
是否有任何关于实际实现的代码参考,例如您的示例1(即一个内部没有等待任何内容的异步方法)? - Wiktor Zychla
在不使用await的方法中使用async修饰符是不必要的,它会为无用的生成一个复杂的状态机。 - Lasse V. Karlsen
3个回答

6
在您的情况下,async操作符会停止方法的执行,直到从LowerLevelCall收到结果。然而,当方法的执行被停止时,await会异步等待,因此线程本身不会被阻塞。在从LowerLevelCall获取结果后,该方法将恢复同步执行。
示例1 - 如果LowerLevelCall需要很长时间才能执行,您的线程将被阻塞,并且只会一直等待,直到LowerLevelCall的执行完成。
示例2 - 如果使用await,则不会阻塞线程,因为await是异步等待的。在LowerLevelCall完成执行后,该方法的结果将分配给您的result变量。 异步和等待介绍 - 本文应该会帮助您开始使用异步和等待。

谢谢大家!这些答案都很有道理!我选择这个作为我的“答案”,因为它简单明了,直接指向另一个有用的资源。 - Rob McCabe

4
在第一个例子中,如果LowerLevelCall(model);需要很长时间,你的结果在这个方法完成之前不会返回,这将阻塞当前线程 - 你必须等待所有这些时间什么都不做。
在第二个例子中,当前线程不会被阻塞,你可以做一些其他事情。当LowerLevelCall(model);完成时,你将异步地获得结果。

3

它们之间的不同在于使用await关键字的函数会等待自己执行完毕后再返回结果。现在,在我进行一些测试的网页上,这两个函数中没有一个阻塞了代码运行,它们都在一个线程上继续运行。

public async Task<IActionResult> ExampleCall([FromBody]ExampleObj model)
{
     // Call some lower level function...
     // ***Here is not return until this function is finish first.***
     var result = await LowerLevelCall(model);
     return result;
}

让我们进入内部... 我创建了两个与你的函数类似的函数。
    public static async Task<bool> Task1()
    {
         await Task.Delay(10000);
         return true;
    }

    public static async Task<bool> Task2()
    {
         Task.Delay(10000);
         return true;
    }

这两个代码的最终版本有很大的不同。

使用await关键字

private void MoveNext()
{
    bool flag;
    int num = this.<>1__state;
    try
    {
        TaskAwaiter awaiter;
        if (num != 0)
        {
            awaiter = Task.Delay(0x2710).GetAwaiter();
            if (!awaiter.IsCompleted)
            {
                this.<>1__state = num = 0;
                this.<>u__1 = awaiter;
                cTestClass.<Task1>d__0 stateMachine = this;
                this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, cTestClass.<Task1>d__0>(ref awaiter, ref stateMachine);
                return;
            }
        }
        else
        {
            awaiter = this.<>u__1;
            this.<>u__1 = new TaskAwaiter();
            this.<>1__state = num = -1;
        }
        awaiter.GetResult();
        awaiter = new TaskAwaiter();
        flag = true;
    }
    catch (Exception exception)
    {
        this.<>1__state = -2;
        this.<>t__builder.SetException(exception);
        return;
    }
    this.<>1__state = -2;
    this.<>t__builder.SetResult(flag);
}

无需

// MoveNext is the name of warped function that call the thread.
private void MoveNext()
{
    bool flag;
    int num = this.<>1__state;
    try
    {
        Task.Delay(0x2710);
        flag = true;
    }
    catch (Exception exception)
    {
        this.<>1__state = -2;
        this.<>t__builder.SetException(exception);
        return;
    }
    this.<>1__state = -2;
    this.<>t__builder.SetResult(flag);
}

一些评论

ASP.NET的内联功能旨在简化和帮助异步执行线程工作。在桌面编程中,它有一个作用,可以避免将“绘制”消息从Windows保留到您的程序中,但在ASP.NET中并没有很多可见的影响,并且增加了很多开销。如果您不确切知道如何使用多任务,它可能会导致更多的延迟而不是帮助,因为所有操作都发生在服务器上,而客户端不需要这种类型的多任务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接