【发布时间】:2020-09-12 21:35:43
【问题描述】:
虽然这个问题似乎已经被问过多次并且已经得到了高度评价的答案,但我想表明多个答案是相互矛盾的,我永远无法完全理解异步代码的内部结构。我完全理解这意味着继续顺序代码执行并稍后完成任务,我正在尝试理解稍后部分。
答案 1 - 建议 UI/Main
首先,this question 内部包含以下测试,表明异步代码在 Main/Ui 线程上运行并链接 article 解释为什么没有其他线程用于异步代码。
问:“在我看来,由于我主要做 UI 开发,所以异步代码是不在 UI 线程上运行的代码,而是在其他线程上运行的代码。”
答:这种信念很普遍,但却是错误的。不要求异步代码在任何第二个线程上运行。
事实上的答案 建议使用线程进行异步编程是“错误的”,说 “线程是工作人员。异步工作流程可以发生在一个线程上。异步工作流程的重点是避免雇用更多工作人员,如果可以避免的话。”
答案 2 - 建议 UI/Main
我读到的下一个问题也建议异步代码运行在 Main/UI 线程上,however the comparison used 是 JavaScript,我们都知道它是一种单线程语言。例如,假设我运行这段代码,
function wait(ms) {
var start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
setTimeout(() => {
wait(5000);
}, 3000)
setTimeout 将被异步调用,在3000ms 之后回调将被添加到Event Loop 并最终运行。然而,方法执行将在 Main/UI 线程上完成,因此导致 UI 被冻结为5000ms。
答案 3 - 建议新线程
This answer 建议在他说的答案中将异步代码运行到一个新线程中。 “当您异步执行某项操作时,您可以在它完成之前继续执行另一个任务。话虽如此,在计算机的上下文中,这转化为在另一个“线程”上执行进程或任务。
答案 4 - 建议新话题
The final answer 建议异步代码是基于线程的,通过说,“在一般情况下,异步调用不一定会创建新线程。这是实现它的一种方法,使用预先存在的线程池或者外部进程是其他方式。它在很大程度上取决于语言、对象模型(如果有的话)和运行时环境。异步只是意味着调用线程不会坐下来等待响应,也不会在调用中发生异步活动线程。”,重点是“也不会在调用线程中发生异步活动”
我不确定从这一点开始,根据我的理解,我认为异步代码必须在不同的线程中执行,永远不要阻塞 UI,我想唯一的例外是 JavaScript。但是,即使涉及在单线程语言上执行异步代码,我也会认为运行的任何函数回调都必须在运行另一个回调之前运行完成。
The second answer on here 通过绘图表明,当异步代码在单个线程上运行时,它会停止并运行不同的异步回调,来回切换,就像线程完成之前一样。这对我来说并不完全有意义,因为对于异步代码,它们通常包含一个回调以防止任何类型的竞争条件,假设 B 需要 A 首先运行完成,B 将是 A 内部的回调。回调 A和 B 不会“一起跑”并在彼此之间切换。
【问题讨论】:
-
I would think Asynchronous code must execute in a different thread- 没有。 stackoverflow.com/q/17661428/11683,blog.stephencleary.com/2013/11/there-is-no-thread.html。您引用的问题中的一些人将线程与任务混淆,甚至将它们视为同一事物,而异步与线程无关。when Asynchronous code is ran on a single thread, it stops and runs a different Asynchronous callback, switching back and forth- stackoverflow.com/q/37419572/11683 -
问题“
Does Asynchronous code run in the UI thread or a new/different thread to not block the UI?”取决于哪种语言的实现。对于 C#、Javascript 和“概念理论”,您会期望(可能)有不同的答案。
标签: multithreading asynchronous threadpool synchronous