3

The point at which I understood the JavaScript event loop was when I heard it described as

"When there is nothing to do, check the queue. But only check the queue when there's nothing left to do."

in the video https://www.youtube.com/watch?v=vMfg0xGjcOI.

For example, if the totality of my JS program is

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);

then the callback function(){console.log("Hey there!");} is put in the queue and thus will be executed after console.log("x = " + x); because that's the point at which there's nothing left to do.

In C#, as I understand -- which I don't really understand -- things are different because the equivalent of the "callback" doesn't wait for there to be nothing to do, but instead interrupts the other process(es). That is my interpretation of

Some time after the write request started, the device finishes writing. It notifies the CPU via an interrupt.

The device driver’s Interrupt Service Routine (ISR) responds to the interrupt. An interrupt is a CPU-level event, temporarily seizing control of the CPU away from whatever thread was running. You could think of an ISR as “borrowing” the currently-running thread, but I prefer to think of ISRs as executing at such a low level that the concept of “thread” doesn’t exist - so they come in “beneath” all threads, so to speak.

Anyway, the ISR is properly written, so all it does is tell the device “thank you for the interrupt” and queue a Deferred Procedure Call (DPC).

When the CPU is done being bothered by interrupts, it will get around to its DPCs. DPCs also execute at a level so low that to speak of “threads” is not quite right; like ISRs, DPCs execute directly on the CPU, “beneath” the threading system.

from http://blog.stephencleary.com/2013/11/there-is-no-thread.html. So if I wrote the equivalent of

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);

in C#, which would be something like

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

the loop for ( var i = 0; i < 10000; ++i ) may in fact be interrupted to deliver the result of SomeAsynchronousRoutine().

Or am I totally wrong and should be ashamed for asking a question without doing enough research first?

If you have to describe the C# "event loop" in terms like

"When there is nothing to do, check the queue. But only check the queue when there's nothing left to do."

then how would you describe it?

user5648283
  • 4,493
  • 3
  • 14
  • 28
  • Javascript execution is strictly singlethreaded for the managed parts, and the native functions with callbacks (e.g. ajax, webworkers) place the callbacks to the same queue. On the other hand, the C# execution is multithreaded, for real. – Koshinae Jan 10 '16 at 21:06
  • @Koshinae I thought the blog post I mentioned says that C# has no concept of a thread http://blog.stephencleary.com/2013/11/there-is-no-thread.html – user5648283 Jan 10 '16 at 21:09
  • @user5648283 Actually, that post says that **there is no thread _in that particular scenario_**, i.e. waiting for an IO task to complete. That doesn't mean that c# has no concept of thread. Threading is a feature of OS, and C# can handle multithreading (quite well, IMHO) – Gian Paolo Jan 10 '16 at 21:25

2 Answers2

4

Because c# is multi threaded and JavaScript is single threaded. I would say it it a bit different.

That await instruction means that the specific half-dozen lines of code you provided will not proceed until the async routine is completed.

But, that doesn't mean that all other code will hang out. Your main thread is free to run other code while this particular routine chills out.

Think about jquery animations. They stop when you're running some long-winded overly complex bit of code, right? Not so with the c# ui. Your ui animation code can run without flicker if you toss that long-winded code inside an anync task and kick it off properly.

Even better -- I could kick off a bunch of async tasks (each long-winded and cumbersome) and they all do their own thing (in their own threads) without bothering eachother (or freezing my ui, or monopolizing an iis request thread, etc).

That obtuse little bit of "wisdom" you quote above is talking about a much deeper question. It's saying "if you have a callback (not an await), how does the cpu manage the interrupt?"

I can't imagine anyone cares about the answer to that question, but maybe I've gotten the gist of what you are asking wrong. Sorry if that's the case!

Hope that's helpful.

Community
  • 1
  • 1
bri
  • 2,524
  • 12
  • 15
3

You are confusing a javascript callback with the await operator in c#, they are not the same. A callback would be the same as an Action in c#

Your example is all wrong.

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);

You would need to do something like this

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);

Now the benefits of C# being multi-threaded is that my callback(Action) will be executed whenever the task scheduler gets around to it, could be at any point in the loop.

Now lets say I wanted the same behavior you experienced with a single thread; you would need to do something like below

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();

Don't worry asynchronous programming in a multi-thread environment is difficult to grasp. One of the reasons I really enjoy golang (chans, range and select? oh my!).

Learn SemaphoreSlim! You can do all kinds of call things, like creating an an AsyncQ!!!

Ryan
  • 102
  • 4