views:

293

answers:

5

I am amazed by the architectural design of node.js and was wondering if C# is capable of such design:

Asynchronous, event based / event loop, non-blocking IO without multithreading.

A: 

Not sure if this is what you're looking for. .NET can do asynchronous callbacks without explicit multi threading.

Jeremy
I am not 100% sure but I sort of think under the hood .NET will create new thread to run events asynchronously I might be wrong though.
Jeffrey C
+1  A: 

your example of node.js is not really applicable since the server that it's running on is performing all the necessary multithreading. If the events are executed based on the same external clock signal, then they're not asynchronous. You can get around this by running another application and that would create two processes on the system.

There is no way that you can make the same application running as a single process on a single system perform asynchronous events without having another thread.

For more details see this Asynchronous vs Multithreading question.

Lirik
Seems I need to get my hands dirty and start deciphering the underlying of libraries like event machine, twisted and node.js. I am interested to really understand how they work.
Jeffrey C
+4  A: 

I think that all the BeginXyz operations that implement the standard asynchronous programming model run the callback on a thread pool thread, which makes the application automatically multi-threaded.

However, you can achieve single-threaded asynchronous programming model by synchronizing all the operations through the single GUI thread that is maintained for windows applications using Control.Invoke or more generally, SynchronizationContext.

Each call to BeginXyz would have to be rewritten along these lines:

// Start asynchronous operation here (1)
var originalContext = SynchronizationContext.Current;
obj.BeginFoo(ar =>
  // Switch to the original thread
  originalContext.Post(ignored => {
    var res = obj.EndFoo(); 
    // Continue here (2)
  }));

The code marked as (2) will continue running on the same thread as the code in (1), so you'll use the thread-pool thread only for forwarding the postback back to the original (single) thread.

As a side-note, this is more directly supported by asynchronous workflows in F# and it can be used for quite elegant style of GUI programming as described here. I don't know node.js, but I suppose that you may be also amazed by F# asynchronous workflows as they are really cool for asynchronous/event based/... style of programming :-)

Tomas Petricek
A: 

The Reactive Extensions for .NET (Rx) is designed for asynchronous and parallel programming. It allows you to program in a reactive vs. interactive way, non-blocking. You use the LINQ query operators, and new ones for IObservable/IObserver interfaces, which are part of Rx. Rx provides the mathematical dual of IEnumerable/IEnumerator, in the form of IObservable/IObserver, which means you can use all of the LINQ standard query operators, in a declarative way, as opposed to using the multithreading APIs directly.

Richard Hein
However, Rx is fully multi-threaded, even though, it could in principle support single-threaded programming model too. My implementation of the same idea was single-threaded (but limited in many ways!) http://tomasp.net/blog/reactive-iv-reactivegame.aspx. Also Rx is now available for JavaScript, and that's certainly single-threaded :-).
Tomas Petricek
+1  A: 

Sure, it just requires an event loop. Something like:

class EventLoop {
   List<Action> MyThingsToDo { get; set; }

   public void WillYouDo(Action thing) {
      this.MyThingsToDo.Add(thing);
   }

   public void Start(Action yourThing) {
      while (true) {
         Do(yourThing);

         foreach (var myThing in this.MyThingsToDo) {
            Do(myThing);
         }
         this.MyThingsToDo.Clear();
      }
   }

   void Do(Action thing) { 
      thing();
   }
}

class Program {
    static readonly EventLoop e = new EventLoop();

    static void Main() {
        e.Start(DoSomething);
    }

    static int i = 0;
    static void DoSomething() {
        Console.WriteLine("Doing something...");
        e.WillYouDo(() => {
            results += (i++).ToString();
        });
        Console.WriteLine(results);
    }

    static string results = "!";
}

Pretty soon, you'll want to get rid of DoSomething and require all work to be registered with MyThingsToDo. Then, you'll want to pass an enum or something to each ThingToDo that tells it why it's doing something. At that point, you'll realize you have a message pump.

BTW, I'd say node.js is glossing over the fact that it's running on an OS and application that's multithreaded. Without that, each call to the network or disk would block.

Mark Brackett
@Mark, is your example non-blocking and asynchronous? All I see is a program that iterate through a list of tasks. And the tasks or in the form of closures.
Jeffrey C
@Jeffrey - yes. You defer the blocking call by delegating it to the EventLoop to run, which means you can run your own tasks prior to the blocking call. Looking closer at node.js, though - they actually *do* take advantage of multiple threads ("Node tells the operating system (through epoll, kqueue, /dev/poll, or select) that it should be notified when the 2 seconds are up"), they're just not explicitly creating them.
Mark Brackett
@Mark, I think I am totally confused now.
Jeffrey C