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.
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.
Not sure if this is what you're looking for. .NET can do asynchronous callbacks without explicit multi threading.
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.
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 :-)
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.
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.