【问题标题】:parallel programming - I need some clarifications并行编程 - 我需要一些说明
【发布时间】:2013-09-26 16:00:52
【问题描述】:

好吧,让我试着用句子来表达......

让我们考虑一个例子, 我创建了一个async 方法并使用await 关键字调用它, 据我所知,

  1. 主线程将被释放
  2. 在单独的线程中,异步方法将开始执行
  3. 一旦它被执行,指针将从它留在主线程中的最后一个位置恢复。

问题一:会回到主线程还是新线程?

问题 2: 如果异步方法受 CPU 限制或网络限制,有什么区别吗?如果是,是什么?

重要的问题

问题 3: 假设这是一个 CPU 密集型方法,我实现了什么?我的意思是 - 主线程被释放,但同时,另一个线程从线程池中使用。有什么意义?

【问题讨论】:

  • 对您的进程进行一次更正,进程进行 1) 主线程执行该函数直到 await 关键字,在此之前的某个时间点,一个新线程启动并在后面工作地面。 2) 主线程停止处理该函数并开始处理消息队列中的其他消息,3) 一旦后台函数完成,它会将一条新消息放入消息队列中,该消息将重新启动 async 函数离开 await 关键字的位置是。
  • 回答问题 3,重点是您的主线程通常执行一组与您的方法不严格相关的指令(例如渲染 UI),因此分配另一个线程来执行 CPU 密集型计算将使您的“软件”避免冻结
  • 好的,所以除了让 ui 响应更快之外,没有其他优势。我以为我会在一段时间内免费获得一个额外的线程。
  • async/await 本身与线程关系不大。简单地将async 添加到方法签名中不会改变代码的行为(并且绝对不会创建额外的线程),除非此方法将开始使用真正的异步方法并使用 await 调用它们。
  • @BilalFazlani - SO 是一个问答网站,我在您的问题中看到 5 个问号,您真正想要的是涵盖整个主题,而不是提出特定问题..

标签: c# asp.net multithreading c#-4.0 asynchronous


【解决方案1】:

async 不会启动新线程。 await 也没有。我建议你阅读我的async intro post 并跟进底部的资源。

async 与并行编程无关;这是关于异步编程的。如果您需要并行编程,请使用任务并行库(例如,PLINQ、Parallel,或者 - 在非常复杂的情况下 - 原始 Tasks)。

例如,您可以有一个 async 方法来执行 I/O 绑定操作。在这种情况下不需要另一个线程,也不会创建任何线程。

如果您确实有一个 CPU-bound 方法,那么您可以使用 Task.Run 创建一个可等待的 Task 在线程池线程上执行该方法。例如,您可以执行await Task.Run(() => Parallel...); 之类的操作,将某些并行处理视为异步操作。

【讨论】:

  • @StephenClearly 我很惊讶地知道并行和异步是不同的!如果我可以问,到底有什么区别
  • @BilalFazlani:“异步”(在async 的意义上)意味着您正在启动一个稍后将完成的操作。 “并行”意味着您正在启动多个线程来进行 CPU 密集型处理。如前所述,async(和await)不会启动后台线程;它们是异步的,但不是并行的。
  • @BilalFazlani:我使用的定义是 IMO 最有意义的定义;他们是相当直白的。经常看到有人使用术语“异步”来在线程池线程上执行某些事情,或者使用术语“并行”来一次做多件事(例如,await)。但我不鼓励这些用法,因为我们需要更清晰的术语。
  • 最后一个 - you are starting an operation that will complete at a later time .. 什么时候?
  • @BilalFazlani:只要它完成。如果是 HTTP 请求,则在您收到响应时。如果是线程池上的并行计算,就是计算完成的时候。
【解决方案2】:
  1. 调用者和async方法的执行将完全在当前线程上。 async 方法不会创建新线程,使用async/await 实际上不会创建额外的线程。相反,线程完成/回调与同步上下文和暂停/给予控制(想想 Node.js 风格的编程)一起使用。但是,当控制权被发送或返回到 await 语句时,它可能最终位于不同的完成线程上(这取决于您的应用程序和其他一些因素)。

  2. 是的,如果它受 CPU 或网络限制,它会运行得更慢。因此await 需要更长的时间。

  3. 好处不在于线程相信与否...异步编程并不一定意味着多线程。好处是您可以在等待async 结果之前继续执行不需要async 结果的其他工作......一个示例是Web 服务器HTTP 侦听器线程池。如果您有一个大小为 20 的池,那么您的限制是 20 个并发请求...如果所有这些请求都将 90% 的时间花在等待数据库工作上,您可以 async/await 数据库工作和您 @987654331 的时间@ 数据库结果回调将被释放...线程将返回到 HTTP 侦听器线程池,另一个用户可以访问您的站点,而原来的用户正在等待数据库工作完成,从而提高了您的总限制。

这实际上是关于释放等待外部绑定和缓慢操作的线程以在这些操作执行时执行其他操作...利用内置线程池。

【讨论】:

  • await 不一定会返回同一个线程。只有当线程是 UI 线程时才会发生这种情况。
  • 嗯,它也不必是 UI 线程,它只需要 SynchronizationContext.Current 而不是返回 null
  • @ScottChamberlain:A SynchronizationContext does not have a 1-to-1 relationship with a thread(链接到我的博客)。一个常见的例子是 ASP.NET SyncCtx,它将将该方法返回到同一个线程。一个不太常见的例子是,如果 Current 设置为 new SynchronizationContext() - 它不会是 null,但也不会使用特定线程。
【解决方案3】:

不要忘记异步部分可能是一些长期运行的工作,例如通过网络运行大型数据库查询、从 Internet 下载文件等。

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 2022-12-17
    • 2013-08-16
    • 2016-06-16
    相关资源
    最近更新 更多