javascript - Javascript 与 C# 中的异步/等待

标签 javascript c# asynchronous async-await

我试图了解异步编程并遇到了 async/await 关键字。我一直在理解 async/await 关键字的使用。我实际上查看了两种编程语言,JavaScript 和 C#,发现两种语言在使用 async/await 关键字方面存在很大差异。
对于 JavaScript,它说:

Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. The await keyword blocks execution of all the code that follows it until the promise fulfills, exactly as it would with a synchronous operation.


链接:https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await#:~:text=Async%2Fawait%20makes%20your%20code,would%20with%20a%20synchronous%20operation .
因此,它说 async/await 将使执行同步。
对于 C#,它说:

The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete.


链接:https://docs.microsoft.com/en-us/dotnet/csharp/async#:~:text=The%20async%20keyword%20turns%20a,used%20inside%20an%20async%20method .
因此,据说使用 async/await 将使代码执行异步。
我想问一下,在 JavaScript 和 C# 中使用 async/await 关键字真的有区别吗?
或者,
上述陈述中是否缺少某些内容?

最佳答案

Javascript 文档说“它让你的代码看起来同步”,它没有说“它让你的代码同步”。
在行为方面,javascript 和 c# 在 async/await 中没有区别。
async 关键字表示该方法中有一个异步操作。
await 关键字有助于将 CPS(延续传递样式)编码为看起来像同步的代码。 CPS 类似于在 promise 之后在 javascript 中使用 then() 或在 C# 任务中使用 ContinueWith()。
'await' 之前的任何代码都在当前线程下同步运行。当执行到'await'时,等待的操作在一个新线程下开始(不一定是新线程,但假设是一个新线程),因此异步操作开始,当前线程被释放。当等待的操作结束时,执行返回到它在'await'关键字中停止的点并继续。
javascript 和 C# 的内部工作方式不同。
Javascript 是事件驱动的。 javascript中有一个主事件循环和一个单线程。当等待的操作完成时,会在后台引发一个事件,主单线程继续执行停止的异步函数。
在 C# 中没有事件循环或单线程。我们应该使用手动线程并在他们完成工作后显式等待并加入它们,或者我们应该使用类似 async/await 之类的东西来代表我们管理线程和延​​续管理。使用 C# 的 async/await 内部使用的 TPL,异步代码的延续使用回调传递给另一个任务。
总之,'await' keywrods 将嵌套的 then() -js- 或 ContinueWith() - c#- 的复杂链变成了看起来像普通的 -synchronous- 代码的简单漂亮的代码。

function doSomethingCPS() {
   asyncOperation1()
      .then(r1 => { consume(r1); return asyncOperation2() })
      .then(r2 => { consume(r2); return asyncOperation3() })
      .then(r3 => { consume(r3); })
}
async function doSomethingAsync() {
   var r1 = await asyncOperation1();
   consume(r1);
   var r2 = await asyncOperation2();
   consume(r2);
   var r3 = await asyncOperation3();
   consume(r3);
}
这两个代码是等价的。但是,很明显后者更简单,更易于阅读。
javascript和c#中的线程管理是有区别的。
据说,在 javascript 中只有一个线程。如果它因任何原因被阻止,该页面将被阻止。当浏览器在 20-30 秒后显示“页面没有响应”或“此页面中有 javascript 代码阻止页面”消息时。
在 HTML5 中引入了工作线程,有助于使用真正的独立线程。这是另一个话题。
你可能会问,如果javascript中只有一个线程,那么一个异步操作到底如何工作,据说可以在另一个线程下工作?!
好问题。在 javascript 中,虽然只有一个线程,但有些对象本身使用单独的线程。计时器 - setInterval() 和 setTimeout()-、XMLHttpObject() 和 fetch() 在这方面是很好的例子。因此,在 javascript 中我们确实可以有异步代码。
最后一点是 C# 使用线程的方式。在 C# 中,async/await 使用名为 TPL(任务并行库)的库工作。 TPL 的核心有一个 Task 类,它类似于异步任务。
我们应该知道的真正一点是,一个Task相当于一个异步操作,但这并不一定意味着一个Task显式使用一个单独的线程。 TPL 中有一个任务调度程序来控制内部线程的使用。如果一个Task的工作很快,使用单独的线程会浪费资源,因此该任务将在当前线程下运行。
我们唯一应该知道的是,Task 是异步代码的逻辑单元。在 fat 中,引入了 Task 让我们摆脱了几乎是低级代码的手动线程管理。
使用 async/await 我们摆脱了提供异步代码所需的所有样板代码。我们可以专注于我们的业务代码。

关于javascript - Javascript 与 C# 中的异步/等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67622770/

相关文章:

javascript - vue 未在实例上定义,但在渲染期间被引用

javascript - ReactJS - 异步调用中的响应

c# - ASP.NET MVC 中异步编程的最佳实践是什么?

c# - 阅读器关闭时调用 Read 的尝试无效。 (C#)

asp.net - 如何防止asp :Timer from sending tick before response is generated?

javascript - Node.js 从回调函数中提取值

javascript - 单击一个链接并调用另一个

javascript - 在 Parse JS API (backbone.js) View 模板中渲染的不仅仅是模型属性

c# - WinForms C# - 自由绘制的正确方法?

reactjs - 如何处理 nextJS 中 useRouter() 的异步问题