首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在.NET中,是否可以使用C#实现不需要多线程的基于事件的异步模式?

在.NET中,是否可以使用C#实现不需要多线程的基于事件的异步模式?
EN

Stack Overflow用户
提问于 2010-05-16 01:09:27
回答 10查看 12K关注 0票数 15

我对Node.js的建筑设计感到惊讶,并想知道C#是否有能力进行这样的设计:

异步的,基于事件的/事件循环,无多线程的非阻塞I/O

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2010-05-16 01:39:00

我认为实现标准异步编程模型的所有BeginXyz操作都在线程池线程上运行回调,这使得应用程序自动多线程。

但是,您可以通过使用Control.Invoke或更一般的SynchronizationContext为windows应用程序维护的单个GUI线程同步所有操作,从而实现单线程异步编程模型。

BeginXyz的每个调用都必须按照以下思路重写:

代码语言:javascript
复制
// 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)
  }));

标记为(2)的代码将继续运行在与(1)中的代码相同的线程上,因此您将只使用线程池线程将回发转发到原始(单)线程。

顺便提一句,F#中的异步工作流更直接地支持这一点,它可以用于相当优雅的GUI编程如前所述风格。我不知道node.js,但我想您可能也会对F#异步工作流感到惊讶,因为它们对于基于异步/事件的/.程序设计风格:-)

票数 13
EN

Stack Overflow用户

发布于 2012-06-22 15:17:26

我正致力于在.NET中作为一个宠物项目来做这样的事情。我叫它ALE (另一个循环事件)..。因为啤酒。

这是极端阿尔法现在,但这都是自制的,因为,像你一样,我想知道它是否可以做到。

  • 这是一个事件循环架构。
  • 它利用.NET的非阻塞异步I/O调用
  • 它使用回调风格的调用来帮助开发人员编写更具可读性的异步代码。
  • 异步web套接字实现
  • 异步http服务器实现
  • 异步sql客户端实现

与其他一些尝试不同,我已经看到它不仅仅是一个带有事件循环的web服务器。您可以在此基础上编写任何基于事件循环的应用程序。

示例

以下代码将:

  • 启动事件循环
  • 在端口1337上启动web服务器
  • 在端口1338上启动web套接字服务器
  • 然后读取一个文件并使用它"DoSomething“:
代码语言:javascript
复制
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);
    });
});

所以我想我的回答是“是的”,它可以在C#.或者几乎任何一种语言。真正的诀窍是能够利用本地的非阻塞I/O。

有关该项目的更多信息将在这里上发布。

票数 8
EN

Stack Overflow用户

发布于 2010-05-16 02:22:39

当然,它只需要一个事件循环。类似于:

代码语言:javascript
复制
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 = "!";
}

很快,您将希望摆脱DoSomething,并要求所有工作都在MyThingsToDo中注册。然后,您需要将一个enum或其他东西传递给每个ThingToDo,它告诉它为什么要做一些事情。到那时,您就会意识到您有一个讯息泵

顺便说一句,我认为node.js是在运行在多线程操作系统和应用程序上的事实。否则,每次对网络或磁盘的调用都会被阻塞。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2842264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档