Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单独使用async/await-over-Task并行库有什么好处?_C#_Multithreading_Asynchronous_Async Await - Fatal编程技术网

C# 单独使用async/await-over-Task并行库有什么好处?

C# 单独使用async/await-over-Task并行库有什么好处?,c#,multithreading,asynchronous,async-await,C#,Multithreading,Asynchronous,Async Await,我知道这个问题可能有点琐碎,但我在网上找到的所有答案都让我感到困惑。 我知道async/await如何工作的基本原理(如何await异步等待任务完成而不阻塞主线程), 但我不理解它的真正好处,因为在我看来,使用async/wait所做的一切都可以使用taskparalel库来完成。 请考虑这个例子,以便更好地理解我的意思: 假设我有一个SuperComplexMethod,它返回一些值,我想并行执行它,同时做一些其他事情。通常我会这样做: internal class Program {

我知道这个问题可能有点琐碎,但我在网上找到的所有答案都让我感到困惑。 我知道
async/await
如何工作的基本原理(如何
await
异步等待任务完成而不阻塞主线程), 但我不理解它的真正好处,因为在我看来,使用async/wait所做的一切都可以使用taskparalel库来完成。 请考虑这个例子,以便更好地理解我的意思: 假设我有一个
SuperComplexMethod
,它返回一些值,我想并行执行它,同时做一些其他事情。通常我会这样做:

internal class Program
{
    private static void Main()
    {
        //I will start a task first that will run asynchroniously  
        var task = Task.Run(() => SuperComplexMethod());

        //Then I will be doing some other work, and then get the result when I need it
        Console.WriteLine("Doing some other work...");
        var result = task.Result;
    }

    static string SuperComplexMethod()
    {
        Console.WriteLine("Doing very complex calculations...");
        Thread.Sleep(3000);
        return "Some result";
    }
} 
下面是我必须如何使用
async/await
完成的:

internal class Program
{
    private static void Main()
    {
        var task = SuperComplexMethodAsync();

        Console.WriteLine("Doing some other work...");
        var result = task.Result;
    }

    //I have to create this async wrapper that can wait for the task to complete
    async static Task<string> SuperComplexMethodAsync()
    {
        return await Task.Run(() => SuperComplexMethod());
    }

    static string SuperComplexMethod()
    {
        Console.WriteLine("Doing very complex calculations...");
        Thread.Sleep(3000);
        return "Some result";
    }
}
内部类程序
{
私有静态void Main()
{
var task=SuperComplexMethodAsync();
Console.WriteLine(“做其他工作…”);
var result=task.result;
}
//我必须创建这个异步包装器,它可以等待任务完成
异步静态任务SuperComplexMethodAsync()
{
返回等待任务。运行(()=>SuperComplexMethod());
}
静态字符串超复杂方法()
{
WriteLine(“进行非常复杂的计算…”);
睡眠(3000);
返回“某个结果”;
}
}
正如您在第二个示例中看到的,为了使用
async/await
方法,我必须创建一个包装器方法来启动任务并异步等待它完成。显然,这对我来说似乎是多余的,因为我可以在不使用标记为
async/await
的包装器的情况下实现完全相同的行为


您能解释一下
async/await
有什么特别之处,以及它比单独使用任务并行库工具有什么实际好处吗?

当使用async和await时,编译器会在后台生成一个状态机

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    // independent work which doesn't need the result of LongRunningOperationAsync can be done here

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); // 1 second delay
    return 1;
}
公共异步任务MyMethodAsync() { Task longRunningTask=LongRunningOperationAsync(); //不需要LongRunningOperationAsync结果的独立工作可以在这里完成 //现在我们呼吁等待这项任务 int result=等待长时间运行任务; //使用结果 控制台写入线(结果); } 公共异步任务LongRunningOperationAsync()//假定此长时间运行的操作返回int { 等待任务。延迟(1000);//1秒延迟 返回1; } 那么这里发生了什么:
  • Task longRunningTask=LongRunningOperationAsync();开始 执行LongRunningOperation

  • 独立的工作是在主线程(线程ID)上完成的 =1)然后到达等待长时间运行的任务

  • 现在,如果longRunningTask尚未完成且仍在运行,MyMethodAsync()将返回其调用方法,因此主线程不会被阻塞。当longRunningTask完成后,线程池中的一个线程(可以是任何线程)将返回到其先前上下文中的MyMethodAsync(),并继续执行(在本例中,将结果打印到控制台)

    第二种情况是longRunningTask已经完成了执行,并且结果可用。当到达Wait longRunningTask时,我们已经得到了结果,因此代码将继续在同一个线程上执行。(在这种情况下,将结果打印到控制台)。当然,对于上面的示例,情况并非如此,其中涉及到Task.Delay(1000)

    更多。。。请参阅:=>


    使用async/await的主要原因可能是线程备用。想象一下以下场景(我将简化以说明问题):a)您有一个web应用程序,它有10个线程可用于处理传入请求;b) 所有请求都涉及I/O(例如连接到远程数据库,通过HTTP/SOAP连接到上游网络服务)来处理/完成;c) 处理每个请求需要2秒钟

    现在想象一下,大约有20个请求同时到达。如果没有async/await,您的web应用程序将开始处理前10个请求。当这种情况发生时,其他10个将在队列中等待2秒钟,您的web应用程序没有线程,因此无法处理它们。只有当前10个完成时,第二个10才开始被处理

    在async/await下,前10个请求将开始执行任务,在等待这些任务时,处理这些任务的线程将返回到web应用程序以处理其他请求。因此,您的web应用程序将几乎立即开始处理第二个10,而不是等待。当前10个等待的任务完成时,web应用程序将继续处理其余的方法,或者在线程池线程上,或者在web应用程序的一个线程上(这取决于您如何配置)。通常,在I/O场景中,I/O是调用持续时间的主要部分,因此我们可以合理地假设,在上述场景中,网络/数据库调用可能需要1.9秒,其余代码(调整DTO、某些业务逻辑等)可能需要0.1秒。如果我们假设延续(在等待之后)是由一个web应用程序线程处理的,那么该线程现在只占用了2秒中的0.1秒,而不是非异步/等待场景中的整整2秒

    你可能会自然而然地想:我只是把线程从一个线程池推到另一个线程池中,这最终也会填满。要理解为什么在真正异步的场景中实际情况并非如此,您需要阅读

    结果是,您现在能够并发处理的请求比可以处理它们的线程多得多

    您会注意到上面的内容主要集中在I/O上,而这正是async/await的亮点所在。如果您的web应用程序通过使用C