代理/ MailboxProcessor在C#中使用新的异步/等待 [英] Agent/MailboxProcessor in C# using new async/await

查看:205
本文介绍了代理/ MailboxProcessor在C#中使用新的异步/等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

通过<一读href=\"http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-10-07-89-59/async_2D00_padl_2D00_$p$p_2D00_publication_2D00_draft_2D00_v2.pdf\">paper关于F#异步,我碰到代理/ MailboxProcessors的话题,它可以被用来实现无状态机。在C#5可以在新的异步/等待功能被用来实现在C#中类似的东西,或者是有一些已经类似物,会更适合?

Reading through a paper about async in F#, I came across the topic of Agents/MailboxProcessors, which can be used to implement reactive state machines. Could the new async/await functionality in C#5 be used to implement something similar in C#, or is there already something analogue that would be better suited?

推荐答案

通过一个位pretty可怕的黑客,你可以使用 MailboxProcessor ​​利用C#类型异步。有些困难是该类型使用一些F#的特定功能(可选参数选项,函数 FSharpFunc 型等。)

With a bit of pretty horrible hacking, you can use the MailboxProcessor type from C# using async. Some difficulties are that the type uses some F# specific features (optional arguments are options, functions are FSharpFunc type, etc.)

从技术上讲,最大的区别是,虽然C#异步创建一个已经运行的任务F#异步的dealyed。这意味着,从C#构造F#异步,你需要编写需要一个方法 UNT - &GT;任务&LT; T&GT; 并创建异步&LT; T&GT; 。我写了一个博客文章,讨论的差异

Technically, the biggest difference is that F# async is dealyed while C# async creates a task that is already running. This means that to construct F# async from C#, you need to write a method that takes unt -> Task<T> and creates Async<T>. I wrote a blog post that discusses the difference.

Anwyay,如果你想尝试,这里是一些code你可以使用:

Anwyay, if you want to experiment, here is some code you can use:

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();
}

正如你所看到的,这看起来很可怕:-)。

As you can see, this looks really horrible :-).


  • 在原则上,它可能可以写一个C#友好包装的 MailboxProcessor ​​键入(只是提取此code丑陋位),但也存在一些问题。

  • In principle, it could be possible to write a C# friendly wrapper for the MailboxProcessor type (just extract the ugly bits from this code), but there are some problems.

在F#你经常用尾递归异步操作来实现状态机在邮箱处理器。如果您在C#写同样的事情,你会最终得到计算器,所以你需要用可变状态写循环。

In F# you often use tail-recursive asyncs to implement the state machine in the mailbox processor. If you write the same thing in C#, you'll eventually get StackOverflow, so you'd need to write loops with mutable state.

这是完全可以写在F#代理并从C#调用它。这仅仅是一个从F#揭C# - 友好界面(使用 Async.StartAsTask 法)的问题。

It is perfectly possible to write the agent in F# and call it from C#. This is just a matter of exposing C#-friendly interface from F# (using the Async.StartAsTask method).

这篇关于代理/ MailboxProcessor在C#中使用新的异步/等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆