.net 4.5中的异步和同步之间的区别

Abr*_*sef 18 .net c# asp.net task-parallel-library async-await

在我阅读.Net 4.5中的异步编程asyncawait关键字时,我在这里阅读以下段落

处理异步请求

在启动时看到大量并发请求或具有突发性负载(并发性突然增加)的Web应用程序中,使这些Web服务调用异步将提高应用程序的响应能力.异步请求与同步请求相同的处理时间.例如,如果请求进行需要两秒钟才能完成的Web服务调用,则无论是同步执行还是异步执行,请求都需要两秒钟.但是,在异步调用期间,在等待第一个请求完成时,不阻止线程响应其他请求.因此,当有许多并发请求调用长时间运行的操作时,异步请求会阻止请求排队和线程池增长.

对于粗体字,我无法理解异步请求如何像同步请求一样处理相同的时间?

例如:

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;
}
Run Code Online (Sandbox Code Playgroud)

我所理解的是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;
    }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,LongRunningOperation()执行期间DoIndependentWork()是否会被另一个线程执行?

i3a*_*non 22

异步操作并不快.如果异步(即await Task.Delay(10000))或同步(即Thread.Sleep(10000))等待10秒,则需要10秒钟.唯一的区别是,第一个不会在等待时保持一个线程但第二个会保持一个线程.

现在,如果您启动任务并且不等待它立即完成,您可以使用相同的线程来执行其他工作,但它不会"加速"异步操作的运行:

var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds
Run Code Online (Sandbox Code Playgroud)

关于你的第二个问题:( 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密集型工作.


Ric*_*ard 5

考虑以下区别:

Thread.Sleep(1000);
Run Code Online (Sandbox Code Playgroud)

await Task.Delay(1000);
Run Code Online (Sandbox Code Playgroud)

两者都需要一秒钟才能运行.但是在前一种情况下,当前线程将被阻塞(并且其所有资源都无用),而在后一种情况下,当前线程可以执行其他有用的操作(例如,提供另一个请求).

异步性不是关于加速单个指令序列,而是能够在同步代码阻塞时执行操作.

回覆.另一个问题

释放的线程将用于其他事情; 在操作完成之前不会分配线程.这是可能的,因为底层操作系统本身是异步的.在上面的示例中,使用了一个计时器,该计时器通知线程在线程空闲时获取,而不是为内部停止的线程.