首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >.net 4.5中异步与同步的区别

.net 4.5中异步与同步的区别
EN

Stack Overflow用户
提问于 2015-01-02 13:02:49
回答 3查看 50.7K关注 0票数 20

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

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

对于粗体的词语,我无法理解异步请求是如何与同步请求处理的时间相同的?

例如,:

代码语言:javascript
运行
复制
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();来执行它?

,如果是,,那么异步编程和多线程编程有什么区别?

更新:

假设代码变成这样:

代码语言:javascript
运行
复制
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()执行期间由另一个线程执行吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-02 13:08:03

异步操作不会更快。如果您异步地等待10秒(即await Task.Delay(10000))或同步(即Thread.Sleep(10000)) ,则需要相同的10秒。唯一的区别是,首先不会在等待时阻塞线程,但是第二个线程将是

现在,如果启动一个任务,而不是等待它立即完成,您可以使用相同的线程执行其他一些工作,但它不会“加快”异步操作的运行:

代码语言:javascript
运行
复制
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仍在“运行”,不需要线程)
  • awaitMyMethod中达到。如果原始任务完成,相同的线程将同步进行,如果没有完成,则返回一个最终将完成的热任务。

因此,使用async-await的事实允许您使用否则会被阻塞的线程,然后同步等待执行CPU密集型的工作。

票数 23
EN

Stack Overflow用户

发布于 2015-01-02 13:12:06

考虑到以下方面的区别:

代码语言:javascript
运行
复制
Thread.Sleep(1000);

代码语言:javascript
运行
复制
await Task.Delay(1000);

两人都要花一秒才能跑。但是,在前一种情况下,当前线程将被阻塞(以及它的所有资源都无用),而在后一种情况下,当前线程可以执行其他有用的事情(例如。送达另一项请求)。

异步性不是关于加速单个指令序列,而是在同步代码被阻塞时能够做一些事情。

Re.另一个问题

释放的线程将用于其他事情;在操作完成之前不会分配线程。这是可能的,因为底层操作系统本身是异步的。在上面的例子中,使用了一个计时器,当线程空闲时,这个定时器会给线程发出信号,而不是一个内部停止的线程。

票数 5
EN

Stack Overflow用户

发布于 2015-01-02 17:33:50

(以I3arnon的答复为基础)

总的来说,使用async-await的同步操作和操作会占用相同的时间,这并不是绝对正确的。

async-await涉及到一些额外的逻辑。检查已完成的服务生和状态机。这使得一些异步操作比相应的同步操作花费更多的时间。

另一方面,大多数适合于async-await的操作都是自然异步的,需要一些额外的处理来使它看起来和感觉是同步的。在这些情况下,异步操作所花费的时间比同步对应的时间要少。

关于这个问题的引文与web应用程序有关。对于web应用程序,异步操作更多的是在可接受的时间内为最大数量的请求提供服务,而不是为每个请求节省几微秒。另一方面,如果涉及到上下文切换,则最终需要更多的时间,这就是为什么在web应用程序中使用Task.Run对应用程序来说弊大于利的原因。

如果您想了解更多关于async-awit的信息,请阅读策展人上的文章。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27742698

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档