我理解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#“事件循环”
“如果无事可做,请检查队列。但只有在没有任何事情要做时才检查队列。”
那你怎么形容呢?
因为c#是多线程和JavaScript is single threaded。我会说它有点不同。
等待指令意味着在异步例程完成之前,您提供的特定的六行代码将不会继续。
但是,这并不意味着所有其他代码都会挂起。当这个特殊程序变冷时,你的主线程可以自由运行其他代码。
想想jquery动画。当你运行一些冗长的过于复杂的代码时,它们会停止,对吧? c#ui不是这样。如果你在任何一个任务中抛出那些冗长的代码并正确启动它,你的ui动画代码可以无闪烁地运行。
更好的是 - 我可以启动一堆异步任务(每个冗长和繁琐)并且他们都做自己的事情(在他们自己的线程中)而不打扰彼此(或冻结我的ui,或垄断iis请求线程,等等)。
你在上面引用的一点点“智慧”是在谈论一个更深层次的问题。它说“如果你有一个回调(不是等待),cpu如何管理中断?”
我无法想象有人会关心这个问题的答案,但也许我已经掌握了你所提出的错误的要点。对不起,如果是这样的话!
希望这很有帮助。
你在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!