Mit ein bisschen ziemlich schrecklichen Hacking, können Sie die MailboxProcessor
Art von C# mit async
verwenden. Einige Schwierigkeiten sind, dass der Typ einige F # spezifische Funktionen verwendet (optionale Argumente sind Optionen, Funktionen sind FSharpFunc
Typ, usw.)
Technisch gesehen ist der größte Unterschied, dass F # Async dealyed wird, während C# Async eine Aufgabe erstellt, die bereits ausgeführt wird . Das bedeutet, dass Sie zum Erstellen von F # -Assync aus C# eine Methode schreiben müssen, die unt -> Task<T>
verwendet und Async<T>
erstellt. Ich schrieb eine blog post that discusses the difference.
Anwyay, wenn Sie experimentieren wollen, hier einige Code, den Sie verwenden können:
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();
}
Wie Sie sehen können, das sieht wirklich schrecklich :-).
Im Prinzip könnte es möglich sein, einen C# freundlichen Wrapper für die MailboxProcessor
Art zu schreiben (extrahiert nur die hässlichen Bits aus diesem Code), aber es gibt einige Probleme.
In F # verwenden Sie häufig tail-rekursive asyncs, um den Zustandsautomaten im Mailbox-Prozessor zu implementieren. Wenn Sie dasselbe in C# schreiben, erhalten Sie schließlich StackOverflow
, also müssten Sie Schleifen mit veränderbarem Status schreiben.
Es ist durchaus möglich, den Agenten in F # zu schreiben und von C# aus aufzurufen. Dies ist nur eine Frage des Freigebens einer C# -freundlichen Schnittstelle von F # (unter Verwendung der Async.StartAsTask
-Methode).
Können Sie den defekten Link reparieren? – czifro
@czifro, ok fertig. – Benjol