在阅读.Net 4.5 async和await关键字中的异步编程时,我阅读了以下段落:这里
处理异步请求 在web应用程序中,如果在启动时看到大量并发请求,或者负载激增(并发性突然增加),则使这些web服务调用异步将提高应用程序的响应能力。异步请求与同步请求处理所需的时间相同。例如,如果一个请求发出一个需要2秒才能完成的web服务调用,那么无论它是同步执行还是异步执行,请求都需要2秒时间。但是,在异步调用期间,当线程等待第一个请求完成时,不会阻止线程响应其他请求。因此,当有许多并发请求调用长期运行的操作时,异步请求会阻止请求队列和线程池的增长。
对于粗体的词语,我无法理解异步请求是如何与同步请求处理的时间相同的?
例如,:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(1000); //1 seconds delay
return 1;
}据我所知,LongRunningOperation()从这里调用Task<int> longRunningTask = LongRunningOperation();的第一行开始执行,并在调用await后返回值,所以从我的观点来看,异步代码比同步代码更快,对吗?
另一个问题:
我的理解是,执行MyMethod()的主线程不会阻止等待LongRunningOperation()的完成,但是它会返回到线程池来服务另一个请求。那么,是否有另一个线程分配给LongRunningOperation();来执行它?
,如果是,,那么异步编程和多线程编程有什么区别?
更新:
假设代码变成这样:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
DoIndependentWork();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
DoSomeWorkNeedsExecution();
await Task.Delay(1000); //1 seconds delay
return 1;
}在这种情况下,LongRunningOperation()会在DoIndependentWork()执行期间由另一个线程执行吗?
发布于 2015-01-02 13:08:03
异步操作不会更快。如果您异步地等待10秒(即await Task.Delay(10000))或同步(即Thread.Sleep(10000)) ,则需要相同的10秒。唯一的区别是,首先不会在等待时阻塞线程,但是第二个线程将是。
现在,如果启动一个任务,而不是等待它立即完成,您可以使用相同的线程执行其他一些工作,但它不会“加快”异步操作的运行:
var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds关于第二个问题:Task.Delay (和其他真正的异步操作一样)不需要执行线程,所以执行没有线。Task.Delay是使用一个触发的System.Threading.Timer实现的,当它完成时它会引发一个事件,同时它不需要线程,因为没有代码要执行。
因此,当运行MyMethod的线程到达await longRunningTask时,它将被释放(只要longRunningTask尚未完成)。如果它是一个ThreadPool线程,它将返回到ThreadPool,在那里它可以处理应用程序中的其他代码。
关于更新,流程如下:
MyMethod开始处理LongRunningOperation开始处理DoSomeWorkNeedsExecution。await中到达一个LongRunningOperation,因此返回一个热门任务。DoIndependentWork由同一个调用线程执行(LongRunningOperation仍在“运行”,不需要线程)await在MyMethod中达到。如果原始任务完成,相同的线程将同步进行,如果没有完成,则返回一个最终将完成的热任务。因此,使用async-await的事实允许您使用否则会被阻塞的线程,然后同步等待执行CPU密集型的工作。
发布于 2015-01-02 13:12:06
考虑到以下方面的区别:
Thread.Sleep(1000);和
await Task.Delay(1000);两人都要花一秒才能跑。但是,在前一种情况下,当前线程将被阻塞(以及它的所有资源都无用),而在后一种情况下,当前线程可以执行其他有用的事情(例如。送达另一项请求)。
异步性不是关于加速单个指令序列,而是在同步代码被阻塞时能够做一些事情。
Re.另一个问题
释放的线程将用于其他事情;在操作完成之前不会分配线程。这是可能的,因为底层操作系统本身是异步的。在上面的例子中,使用了一个计时器,当线程空闲时,这个定时器会给线程发出信号,而不是一个内部停止的线程。
发布于 2015-01-02 17:33:50
(以I3arnon的答复为基础)
总的来说,使用async-await的同步操作和操作会占用相同的时间,这并不是绝对正确的。
async-await涉及到一些额外的逻辑。检查已完成的服务生和状态机。这使得一些异步操作比相应的同步操作花费更多的时间。
另一方面,大多数适合于async-await的操作都是自然异步的,需要一些额外的处理来使它看起来和感觉是同步的。在这些情况下,异步操作所花费的时间比同步对应的时间要少。
关于这个问题的引文与web应用程序有关。对于web应用程序,异步操作更多的是在可接受的时间内为最大数量的请求提供服务,而不是为每个请求节省几微秒。另一方面,如果涉及到上下文切换,则最终需要更多的时间,这就是为什么在web应用程序中使用Task.Run对应用程序来说弊大于利的原因。
如果您想了解更多关于async-awit的信息,请阅读策展人上的文章。
https://stackoverflow.com/questions/27742698
复制相似问题