虽然这个问题似乎已经被问了很多次,而且我已经得到了很高的答案,但我想指出,多个答案是相互冲突的,而且我永远无法完全理解异步代码的内部结构。我完全理解它的意思是继续顺序代码执行并在以后完成任务,我正在努力理解后面的部分。
答案1-建议UI/Main
首先,这个问题包含了下面的测试,建议异步代码运行在main/UI线程上,并链接了一篇文章,解释为什么异步代码没有其他线程。
问:“在我看来,由于我主要做UI开发,异步代码是不在UI线程上运行的代码,而是在其他线程上运行的代码。”
function wait(ms) {
var start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
setTimeout(() => {
wait(5000);
}, 3000)
SetTimeout
将异步调用,在3000ms
之后,回调将添加到事件循环
中,并最终运行。但是,方法执行将在main/UI线程上完成,因此导致UI被冻结5000ms
。
答案3-建议新线程
他说,这个答案暗示异步代码运行到一个新线程中。当你异步执行某件事时,你可以在它完成之前转到另一个任务。这就是说,在计算机的上下文中,这就转化为在另一个“线程”上执行一个进程或任务。
最后的答案表明异步代码是基于线程的,它说:“在一般情况下,异步调用不一定会创建一个新的线程。这是实现它的一种方法,预先存在的线程池或外部进程是其他方法。它严重依赖于语言、对象模型(如果有的话)和运行时环境。异步只是指调用线程不坐着等待响应,也不是异步活动发生在调用线程中。”,其要点是“异步活动也不发生在调用线程中”。
我不确定从这一点上该怎么走,根据我的理解,我认为异步代码必须在不同的线程中执行,以永远不会阻塞UI,我想唯一的例外是JavaScript。然而,即使涉及在单线程语言上执行异步代码,我也会认为,运行的任何函数回调都必须在运行另一个回调之前运行完成。
这里的第二个答案是这样的:当异步代码在单个线程上运行时,它会停止并运行一个不同的异步回调,来回切换,就像线程在它们完成之前所做的那样。对我来说,这并不完全有意义,因为对于异步代码,它们通常包含一个回调以防止任何类型的竞争条件,假设B要求a首先运行到完成,B将是a内部的回调。回调a和B将不会“一起运行”并在彼此之间切换。
让我们从“低级”开始工作。
对于低层硬件,大多数现代设备(网络、磁盘)使用总线主控或DMA进行到/从计算机主存储器的传输,并在传输完成时生成IRQ;并支持“驱动程序向设备发出命令,然后设备在命令完成时发出IRQ”的模式,以解决不涉及IO的问题。举个例子;如果你想(例如)在单CPU计算机上异步读取磁盘数据;CPU(设备驱动程序)可以告诉磁盘控制器硬件要做什么,然后CPU可以在磁盘控制器传输数据的同时继续做有用的工作,然后当IRQ到达时(发出传输完成的信号),它可以触发某种“异步传输完成”动作。
如果设备不支持这一点(例如,必须使用某种“编程IO”,其中需要使用CPU来传输数据等),那么异步性将不得不以某种方式进行仿真--通过使用另一个CPU,通过说谎(同步进行并假装“异步完成”立即发生),或者通过使用一个在不同工作(一个请求异步操作,另一个正在进行异步操作)之间快速切换的CPU来创建异步性的假象。
上一层是操作系统的内核和设备驱动程序。对于几乎所有的现代操作系统,所有需要足够时间才值得关心的事情都是(内部)完全异步的(即使底层硬件不支持的时候,异步操作也是仿真的);主要是因为多处理和性能(例如,确保来自不同进程的不同请求能够使所有硬件设备在可能的情况下并行地完成有用的工作,通常使用IO优先级来尝试确保更重要的工作比不重要的工作更快完成,通常结合后台发生的各种预取策略来增加工作在任何进程请求之前完成的机会)。然而;提供给用户空间的API可能不会向用户空间进程公开内核对异步操作的支持。例如,最初的POSIX API根本不支持异步操作(在为时已晚之后,它在顶部被反向攻击,这就是为什么您仍然不能执行诸如异步打开文件这样的基本操作)。
上一层是语言的运行时。这介于语言的标准(它可能满足也可能不满足异步操作,可能有也可能没有某种“用户空间线程/纤维/什么”)和内核的API(它可能提供或不提供某些/任何异步操作)之间。对于语言的运行时支持异步操作但底层内核API不支持的情况,必须以某种方式对其进行仿真-例如,使用(一个,多个?)“内核线程”(并可能隐藏在任何类型的“用户空间线程/纤维/什么”之后),或者通过说谎(同步执行并假装“异步完成”立即发生)。
最后一层是第三方库/模块/包,用于在最初不支持它们的语言之上添加异步操作。这总是涉及某种模拟。
请注意,如果您查看整个层集,系统作为一个整体可以在两个不同的级别(在内核/设备驱动程序,加上在语言运行时的用户空间或其之上)模拟异步操作;因此,可以同时使用两种不同的方法来模拟异步性(即使在这种情况下,也不可能使用线程/任务来模拟/提供异步性)。
当然,如果有100种语言,平均每种语言有4个实现;那么将有400个排列,它们可能对异步操作的实际实现方式都有不同的答案;因此,您可能会对C#、Javascript、...有不同的答案(可能),它们(对于该语言的实现)可能是正确的,尽管(对于该语言的其他实现)可能是错误的。
本文向大家介绍Jquery ajax 同步阻塞引起的UI线程阻塞问题,包括了Jquery ajax 同步阻塞引起的UI线程阻塞问题的使用技巧和注意事项,需要的朋友参考一下 最近做一个项目,遇到了一个问题同步ajax引起的ui线程阻塞问题,下面把我的问题解决过程分享给大家。 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收
问题内容: 当用户选择在另一个线程中启动阻止进程的菜单项时,我试图在JavaFX 8应用程序中提供反馈。在我的实际应用程序中,它是文件下载,但是通过示例,我使用最少的代码创建了一个测试用例: 它的工作方式如下:当选择“开始”菜单项时,主菜单文本应立即更改为“正在运行…”,然后应附加“完成!”。经过5秒钟的模拟我的文件下载的睡眠。 实际上发生的是,即使我正在使用,在阻止过程完成 后 , 两个 文本更
在UI线程中运行代码的观点中,以下两者之间有什么区别吗: 或 而且
问题内容: 我发现我的某些活动在启动时被阻止。因此,我在一个新项目中编写了该代码: 结果是第一次创建AdView对象会阻塞UI线程1到2秒钟。 有什么办法可以避免这种情况? 谢谢 问题答案: 您正在UI线程中创建AdView,这就是被阻止的原因。在AdView初始化期间,线程不会执行其他任何操作。 您可以尝试在另一个线程中加载AdView,也可以使用AsyncTask以用户界面安全的方式加载它。
问题内容: 据我所知,在android中,当我们运行进程时,它们始于Main线程。当我们做一些繁重的工作时,我们使用了一个新线程。如果我们想修改UI外观,可以使用在UI上运行。 有人可以向我解释这些线程的作用以及如何使用它们吗? 问题答案: UI线程和主线程只是同一线程的不同名称。 应用程序的所有UI膨胀都在此主线程上完成。之所以将“较重”的工作委派给其他线程,是因为我们不希望这些操作减慢UI的响