C#"事件如何循环"比较JavaScript"事件循环"?

时间:2016-01-10 20:36:06

标签: javascript c# asynchronous async-await

我理解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;不会等待那里无所事事,而是中断其他进程。这是我对

的解释
  

写入请求开始后的一段时间,设备完成   写作。它通过中断通知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#&#34;事件循环&#34;就像

这样的术语
  

&#34;当无事可做时,请检查队列。但只有在没有任何事情要做时才检查队列。&#34;

然后你会如何描述它?

2 个答案:

答案 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 !!!