gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:02:00 26 4
gpt4 key购买 nike

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

阅读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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com