Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible in .NET, using C#, to achieve event based asynchronous pattern without multithreading?

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

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

like image 347
Jeff Avatar asked May 16 '10 01:05

Jeff


People also ask

Is .NET same as C?

C# is a programming language and . NET is a framework. . NET has Common Language Runtime (CLR), which is a virtual component of .

What language does .NET use?

C# (pronounced “see-sharp”) is the actual coding language that we write inside of the . NET framework.

Can .NET run C++?

You can program in C++ using visual studio . NET. Well that's what it was called along time ago.


4 Answers

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

like image 115
Tomas Petricek Avatar answered Nov 05 '22 10:11

Tomas Petricek


I'm working on just such a thing in .NET as a pet project. I call it ALE (Another Looping Event)... because beer.

It's extremely alpha right now, but it's all homebrew because, like you, I wanted to know if it can be done.

  • It's an event loop architecture.
  • It leverages .NET's non-blocking async I/O calls
  • It uses callback-style calls to assist developers writing async code that is a little more readable.
  • Async web sockets implementation
  • Async http server implementation
  • Async sql client implemenation

Unlike some of the other tries at this I've seen it's not just a web server with an event loop. You could write any sort of event loop based application off of this.


Example

The following code will:

  • Start the Event Loop
  • Start a web server on port 1337
  • Start a web socket server on port 1338
  • Then read a file and "DoSomething" with it:
EventLoop.Start(() => {

    //create a web server
    Server.Create((req, res) => {
        res.Write("<h1>Hello World</h1>");
    }).Listen("http://*:1337");


    //start a web socket server
    Net.CreateServer((socket) => {
        socket.Receive((text) => {
             socket.Send("Echo: " + text);
        });
    }).Listen("127.0.0.1", 1338, "http://origin.com");


    //Read a file
    File.ReadAllText(@"C:\Foo.txt", (text) => {
        DoSomething(text);
    });
});

So I guess my answer is "Yes", it can be done in C#... or almost any language for that matter. The real trick is being able to leverage native non-blocking I/O.

More information about the project will be posted here.

like image 21
Ben Lesh Avatar answered Nov 05 '22 11:11

Ben Lesh


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.

like image 39
Mark Brackett Avatar answered Nov 05 '22 09:11

Mark Brackett


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.

like image 20
Richard Anthony Freeman-Hein Avatar answered Nov 05 '22 11:11

Richard Anthony Freeman-Hein