代码之家  ›  专栏  ›  技术社区  ›  Benjol

C中的代理/邮箱处理器使用新的异步/等待

  •  7
  • Benjol  · 技术社区  · 14 年前

    这个问题包含两个我不完全理解的主题

    通读 paper 关于f_中的异步,我遇到了agents/mailboxprocessors这个主题,它可以用来实现反应状态机。C 5中新的异步/等待功能是否可以用于实现C中类似的功能,或者已经有了更适合的类似功能?

    3 回复  |  直到 7 年前
        1
  •  11
  •   ChaosPandion    14 年前

    有点可怕的黑客攻击,你可以使用 MailboxProcessor 使用c输入 async 是的。有些困难是类型使用了一些特定于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();
    }
    

    如你所见,这看起来真的很可怕。

    • 原则上,可以为 邮箱处理器 类型(仅从代码中提取丑陋的位),但存在一些问题。

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

    • 完全有可能将代理写在f中,然后从c调用它。这只是从f公开c友好界面的问题(使用 Async.StartAsTask 方法)。

        2
  •  3
  •   Brian    14 年前

    原则上,我希望将这些f api转换为c plus async await会很简单。

    在实践中,我不清楚它是否会变得漂亮,或者丑陋,并且充满了额外的类型注释,或者仅仅是不习惯,需要一些api消息来让它在c中感觉更自在。我认为在有人做这项工作并尝试之前,陪审团是不存在的。(我想在等待的CTP中没有这样的样品。)

        3
  •  0
  •   user29439user29439    12 年前

    你可以看看 Stact 是的。它已经有一段时间没有更新了,但是如果你想做一些有更好的C支持的东西,你可能会发现它是一个很好的起点。不过,我不认为它是async/await的最新版本。