我理解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#中,据我所知 - 我并不是真正理解 - 事情是不同的,因为相当于&#34;回调&#34;不会等待那里无所事事,而是中断其他进程。这是我对
的解释来自http://blog.stephencleary.com/2013/11/there-is-no-thread.html的写入请求开始后的一段时间,设备完成 写作。它通过中断通知CPU。
设备驱动程序的中断服务程序(ISR)响应 打断。中断是CPU级事件,暂时占用 控制CPU远离正在运行的任何线程。你可以 将ISR视为“借用”当前正在运行的线程,但我 我更愿意将ISR视为执行在如此低的水平 “线程”的概念不存在 - 因此它们都在“下方”进入 线索,可以这么说。
无论如何,ISR是正确编写的,所以它只是告诉设备 “谢谢你的中断”并排队延期程序调用 (DPC)。
当CPU被中断困扰时,它会绕过 它的DPC。 DPC的执行水平也很低,可以说 “线程”不太对劲;像ISR一样,DPC直接在 CPU,在线程系统“下方”。
。所以,如果我写了相当于
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#&#34;事件循环&#34;就像
这样的术语&#34;当无事可做时,请检查队列。但只有在没有任何事情要做时才检查队列。&#34;
然后你会如何描述它?
答案 0 :(得分:2)
因为c#是多线程的JavaScript is single threaded。我会说它有点不同。
等待指令意味着您提供的特定的六行代码不会继续,直到异步例程完成。
但是,这并不意味着所有其他代码会挂掉。当这个特殊程序变冷时,你的主线程可以自由运行其他代码。
考虑jquery动画。当你运行一些冗长过于复杂的代码时,它们会停止,对吧? c#ui不是这样。如果你在任何一个任务中抛出那些冗长的代码并正确启动它,你的ui动画代码可以无闪烁地运行。
更好 - 我可以启动一堆异步任务(每个冗长且繁琐)并且他们都做自己的事情(在他们自己的线程中)而不打扰彼此(或冻结我的ui,或垄断iis请求线程等。)
那种愚蠢的智慧&#34;你在上面引用的是一个更深层次的问题。它说&#34;如果你有一个回调(不是等待),cpu如何管理中断?&#34;
我无法想象有人会关心这个问题的答案,但也许我已经明白了你所提出的错误的要点。对不起,如果是这样的话!
希望有所帮助。
答案 1 :(得分:0)
您正在将JavaScript回调与c#中的await运算符混淆,它们并不相同。回调与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#是多线程的好处是,只要任务计划程序在循环中的任何时候执行它,我的callback(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的原因之一(chan,范围和选择?哦,我的天!)。
学习SemaphoreSlim
!您可以进行各种呼叫操作,例如创建AsyncQ !!!