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;
}
那么这里发生了什么:
使用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