C#“事件循环”与JavaScript“事件循环”相比如何?

问题描述 投票:1回答:2

我理解JavaScript事件循环的时刻就是我听到它描述的时候

“如果无事可做,请检查队列。但只有在没有任何事情要做时才检查队列。”

在视频https://www.youtube.com/watch?v=vMfg0xGjcOI

例如,如果我的JS程序的总体是

var x = 5.0;  
setTimeout(0,function(){console.log("Hey there!");});
for ( var i = 0; i < 10000; ++i ) x = Math.sqrt(x);
console.log("x = " + x);

然后回调function(){console.log("Hey there!");}被放入队列中,因此将在console.log("x = " + x);之后执行,因为这是没有什么可做的点。

在C#中,正如我所理解的那样 - 我并不真正理解 - 事情是不同的,因为“回调”的等价物并不等待无所事事,而是中断其他进程。这是我的解释

写入请求开始后的一段时间,设备完成写入。它通过中断通知CPU。

设备驱动程序的中断服务程序(ISR)响应中断。中断是CPU级事件,暂时控制CPU远离正在运行的任何线程。您可以将ISR视为“借用”当前运行的线程,但我更倾向于将ISR视为执行在如此低的水平以至于“线程”的概念不存在 - 因此它们进入“低于”所有线程,可以这么说。

无论如何,ISR是正确编写的,所以它只是告诉设备“谢谢你的中断”并排队延迟过程调用(DPC)。

当CPU完成被中断困扰时,它将绕过它的DPC。 DPC也在如此低的水平上执行,以至于说“线程”不是很正确;像ISR一样,DPC直接在CPU上执行,在线程系统“下方”执行。

来自http://blog.stephencleary.com/2013/11/there-is-no-thread.html。所以,如果我写了相当于

var x = 5.0;  
setTimeout(0,function(){console.log("Hey there!");});
for ( var i = 0; i < 10000; ++i ) x = Math.sqrt(x);
console.log("x = " + x);

在C#中,这将是类似的东西

var x = 5.0;  
await SomeAsynchronousRoutine();
for ( var i = 0; i < 10000; ++i ) x = Math.Sqrt(x);
Console.WriteLine("x = {0}",x);   

实际上可以中断循环for ( var i = 0; i < 10000; ++i )以传递SomeAsynchronousRoutine()的结果。

或者我完全错了,在没有做足够的研究的情况下提出问题应该感到羞耻?

如果你必须按照这样的术语描述C#“事件循环”

“如果无事可做,请检查队列。但只有在没有任何事情要做时才检查队列。”

那你怎么形容呢?

javascript c# asynchronous async-await
2个回答
2
投票

因为c#是多线程和JavaScript is single threaded。我会说它有点不同。

等待指令意味着在异步例程完成之前,您提供的特定的六行代码将不会继续。

但是,这并不意味着所有其他代码都会挂起。当这个特殊程序变冷时,你的主线程可以自由运行其他代码。

想想jquery动画。当你运行一些冗长的过于复杂的代码时,它们会停止,对吧? c#ui不是这样。如果你在任何一个任务中抛出那些冗长的代码并正确启动它,你的ui动画代码可以无闪烁地运行。

更好的是 - 我可以启动一堆异步任务(每个冗长和繁琐)并且他们都做自己的事情(在他们自己的线程中)而不打扰彼此(或冻结我的ui,或垄断iis请求线程,等等)。

你在上面引用的一点点“智慧”是在谈论一个更深层次的问题。它说“如果你有一个回调(不是等待),cpu如何管理中断?”

我无法想象有人会关心这个问题的答案,但也许我已经掌握了你所提出的错误的要点。对不起,如果是这样的话!

希望这很有帮助。


0
投票

你在c#中使用await运算符混淆了一个javascript回调,它们不一样。回调与c#中的Action相同

你的例子都错了。

var x = 5.0;
setTimeout(0,function(){console.log("Hey there!");});
for ( var i = 0; i < 10000; ++i ) x = Math.sqrt(x);
console.log("x = " + x);
var x = 5.0;
await SomeAsynchronousRoutine();
for ( var i = 0; i < 10000; ++i ) x = Math.Sqrt(x);
Console.WriteLine("x = {0}",x);

你需要做这样的事情

var x = 5.0;
Task.Run(() => {
   Console.WriteLine("Hey there!");
});
for ( var i = 0; i < 10000; ++i ) x = Math.Sqrt(x);
Console.WriteLine("x = {0}",x);

现在C#是多线程的好处是我的回调(Action)将在任务调度程序到达时执行,可以在循环中的任何点。

现在让我们说我想要一个单线程所遇到的相同行为;你需要做类似下面的事情

var x = 5.0;
var lck = new SemaphoreSlim(1);
Task.Run(async () => {
   await lck.WaitAsync();
   Console.WriteLine("Hey there!");
});
for ( var i = 0; i < 10000; ++i ) x = Math.Sqrt(x);
Console.WriteLine("x = {0}",x);
lck.Release();

不要担心多线程环境中的异步编程很难掌握。我非常喜欢golang的原因之一(chans,范围和选择?哦,我的!)。

学习SemaphoreSlim!你可以做各种各样的通话,比如创建一个AsyncQ!

© www.soinside.com 2019 - 2024. All rights reserved.