8

この質問は、私が完全には理解していない 2 つのトピックを組み合わせたものです

F# の asyncに関する論文を読んで、リアクティブ ステート マシンの実装に使用できる Agents/MailboxProcessors のトピックに出会いました。C#5 の新しい async/await 機能を使用して、C# で同様のものを実装できますか?それとも、より適したアナログが既に存在しますか?

4

3 に答える 3

11

少し恐ろしいハッキングで、MailboxProcessorC# を使用して型を使用できますasync。いくつかの問題は、型がいくつかの F# 固有の機能を使用していることです (オプションの引数はオプション、関数はFSharpFunc型など)。

技術的には、最大の違いは、F# の async が処理され、C# の async が既に実行中のタスクを作成することです。つまり、C# から F# async を構築するには、 を取得して作成するメソッドをunt -> Task<T>作成する必要がありますAsync<T>この違いについて説明するブログ記事を書きました。

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

ご覧のとおり、これは本当にひどいものに見えます :-)。

  • 原則として、この型の C# に適したラッパーを作成することは可能ですがMailboxProcessor(このコードから醜い部分を抽出するだけです)、いくつかの問題があります。

  • F# では、末尾再帰非同期を使用して、メールボックス プロセッサにステート マシンを実装することがよくあります。C# で同じことを書くと最終的にはStackOverflowになるので、変更可能な状態でループを記述する必要があります。

  • F# でエージェントを作成し、C# から呼び出すことは完全に可能です。これは、(メソッドを使用して) F# から C# に適したインターフェイスを公開するだけの問題ですAsync.StartAsTask

于 2010-11-02T13:43:58.043 に答える
3

原則として、これらの F# API を C#-plus-async-await に変換するのは簡単だと思います。

実際には、それが美しいものになるのか、それとも醜く余分な型注釈でいっぱいになるのか、それとも単純に慣用的ではなく、C# でより使いやすくするために何らかの API マッサージが必要になるのかはわかりません。誰かが仕事をして試してみるまで、陪審員は出ていないと思います。(await CTP にはそのようなサンプルはないと思います。)

于 2010-11-02T05:54:19.017 に答える
0

Stactを見てみてはいかがでしょうか。しばらくの間更新されていませんが、C#のサポートが少し優れているものを作成したい場合は、出発点として適していると思われるかもしれません。ただし、async/awaitは最新ではないと思います。

于 2012-04-03T03:12:28.123 に答える