c# - C# 中的 Agent/MailboxProcessor 使用新的 async/await

标签 c# f# agent c#-to-f# async-await

这个问题结合了我不完全理解的两个主题

阅读paper关于 F# 中的异步,我遇到了 Agents/MailboxProcessors 的主题,它可用于实现响应式(Reactive)状态机。 C#5 中新的 async/await 功能是否可以用于在 C# 中实现类似的东西,或者是否已经有一些更适合的类似物?

最佳答案

通过一些非常可怕的黑客攻击,您可以使用 MailboxProcessor使用 async 从 C# 键入.一些困难是该类型使用了一些 F# 特定的功能(可选参数是选项,函数是 FSharpFunc 类型等)

从技术上讲,最大的区别是 F# async 被处理,而 C# async 创建一个已经在运行的任务。这意味着要从 C# 构造 F# async,您需要编写一个采用 unt -> Task<T> 的方法。并创建 Async<T> .我写了一个blog post that discusses the difference .

Anwyay,如果你想做实验,这里有一些你可以使用的代码:

static FSharpAsync<T> CreateAsync<T>(Func<Task<T>> f)
{ 
  return FSharpAsync.FromContinuations<T>(
    FuncConvert.ToFSharpFunc<
      Tuple< FSharpFunc<T, Unit>, 
             FSharpFunc<Exception, Unit>,
             FSharpFunc<OperationCanceledException, Unit> >>(conts => {
    f().ContinueWith(task => {
      try { conts.Item1.Invoke(task.Result); }
      catch (Exception e) { conts.Item2.Invoke(e); }
    });
  }));
}

static void MailboxProcessor() {
  var body = FuncConvert.ToFSharpFunc<
                FSharpMailboxProcessor<int>, 
                FSharpAsync<Unit>>(mbox =>
    CreateAsync<Unit>(async () => {
      while (true) {
        var msg = await FSharpAsync.StartAsTask
          ( mbox.Receive(FSharpOption<int>.None), 
            FSharpOption<TaskCreationOptions>.None, 
            FSharpOption<CancellationToken>.None );
        Console.WriteLine(msg);
      }
      return null;
    }));
  var agent = FSharpMailboxProcessor<int>.Start(body,
                FSharpOption<CancellationToken>.None);
  agent.Post(1);
  agent.Post(2);
  agent.Post(3);
  Console.ReadLine();
}

如您所见,这看起来真的很糟糕 :-)。

  • 原则上,可以为 MailboxProcessor 编写一个 C# 友好的包装器。类型(只是从这段代码中提取丑陋的部分),但存在一些问题。

  • 在 F# 中,您经常使用尾递归异步在邮箱处理器中实现状态机。如果你用 C# 写同样的东西,你最终会得到 StackOverflow ,因此您需要编写具有可变状态的循环。

  • 完全可以用 F# 编写代理并从 C# 调用它。这只是从 F# 公开 C# 友好接口(interface)的问题(使用 Async.StartAsTask 方法)。

关于c# - C# 中的 Agent/MailboxProcessor 使用新的 async/await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4075189/

相关文章:

c# - Visual Studio 和 .NET 中的条件文件编译

c# - 排序字符串列表的最快方法

f# - 如何将缺失值转换为字符串?

f# - Seq.find 大量崩溃(int64)

c# - F# 中的记录实例在 C# 中为空

gwt - GWT user.agent属性以及它们对应的浏览器的权威列表

artificial-intelligence - 人工智能 - 清洁和油漆的智能代理

c# - 获取联系人的 TFS 项目

c# - 如何在 C# 中同时检测多个按键? (鼓应用)

javascript - 在运行的 node.js 进程中动态加载 Node 模块