如何从 C# 调用和处理异步 F# 工作流
我读过一些 F# 教程,并且注意到与 C# 相比,在 F# 中执行异步和并行编程是多么容易。因此,我试图编写一个 F# 库,它将从 C# 调用,并采用 C# 函数(委托)作为参数并异步运行它。
到目前为止,我已经成功地传递了该函数(我什至可以取消),但我错过的是如何实现回调回 C#,该回调将在异步操作完成后立即执行。 (例如函数AsynchronousTaskCompleted?)。另外,我想知道是否可以从 AsynchronousTask 函数将(例如进度%)发回 F#。
有人可以帮我吗?
这是我到目前为止编写的代码(我不熟悉 F#,因此以下代码可能是错误的或实现得不好)。
//C# Code Implementation (How I make the calls/handling)
//Action definition is: public delegate void Action();
Action action = new Action(AsynchronousTask);
Action cancelAction = new Action(AsynchronousTaskCancelled);
myAsyncUtility.StartTask2(action, cancelAction);
Debug.WriteLine("0. The task is in progress and current thread is not blocked");
......
private void AsynchronousTask()
{
//Perform a time-consuming task
Debug.WriteLine("1. Asynchronous task has started.");
System.Threading.Thread.Sleep(7000);
//Post progress back to F# progress window?
System.Threading.Thread.Sleep(2000);
}
private void AsynchronousTaskCompleted(IAsyncResult asyncResult)
{
Debug.WriteLine("2. The Asynchronous task has been completed - Event Raised");
}
private void AsynchronousTaskCancelled()
{
Debug.WriteLine("3. The Asynchronous task has been cancelled - Event Raised");
}
//F# Code Implementation
member x.StartTask2(action:Action, cancelAction:Action) =
async {
do! Async.FromBeginEnd(action.BeginInvoke, action.EndInvoke, cancelAction.Invoke)
}|> Async.StartImmediate
do printfn "This code should run before the asynchronous operation is completed"
let progressWindow = new TaskProgressWindow()
progressWindow.Run() //This class(type in F#) shows a dialog with a cancel button
//When the cancel button is pressed I call Async.CancelDefaultToken()
member x.Cancel() =
Async.CancelDefaultToken()
I have read few F# tutorials and I have noticed how easy is to perform asynchronous and parallel programming in F# compared to C#. Thus, I am trying to write an F# library which will be called from C# and take take a C# function (delegate) as a parameter and run it asynchronously.
I have managed to pass the function so far (I am even able to cancel) but what I miss is how to implement a callback back to C# which will be executed it as soon as the asynchronous operation is completed. (e.g. the function AsynchronousTaskCompleted?). Also I was wondering if I can post (e.g. Progress %) back to F# from then function AsynchronousTask.
Can someone please help me?
This is the code I have written so far (I am not familiar with F# so the following code may be wrong or poorly implemented).
//C# Code Implementation (How I make the calls/handling)
//Action definition is: public delegate void Action();
Action action = new Action(AsynchronousTask);
Action cancelAction = new Action(AsynchronousTaskCancelled);
myAsyncUtility.StartTask2(action, cancelAction);
Debug.WriteLine("0. The task is in progress and current thread is not blocked");
......
private void AsynchronousTask()
{
//Perform a time-consuming task
Debug.WriteLine("1. Asynchronous task has started.");
System.Threading.Thread.Sleep(7000);
//Post progress back to F# progress window?
System.Threading.Thread.Sleep(2000);
}
private void AsynchronousTaskCompleted(IAsyncResult asyncResult)
{
Debug.WriteLine("2. The Asynchronous task has been completed - Event Raised");
}
private void AsynchronousTaskCancelled()
{
Debug.WriteLine("3. The Asynchronous task has been cancelled - Event Raised");
}
//F# Code Implementation
member x.StartTask2(action:Action, cancelAction:Action) =
async {
do! Async.FromBeginEnd(action.BeginInvoke, action.EndInvoke, cancelAction.Invoke)
}|> Async.StartImmediate
do printfn "This code should run before the asynchronous operation is completed"
let progressWindow = new TaskProgressWindow()
progressWindow.Run() //This class(type in F#) shows a dialog with a cancel button
//When the cancel button is pressed I call Async.CancelDefaultToken()
member x.Cancel() =
Async.CancelDefaultToken()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
要获得 F# 异步工作流程的优势,您必须在 F# 中实际编写异步计算。您尝试编写的代码将不起作用(即它可能会运行,但不会有用)。
当您在 F# 中编写异步计算时,可以使用
let!
和do!
进行异步调用。这允许您使用其他原始的非阻塞计算。例如,您可以使用Async.Sleep
而不是Thread.Sleep
。您只能在
async
块内使用异步操作,并且它依赖于 F# 编译器处理do!
和let!
的方式。对于以顺序方式编写的代码(例如在 C# 中或在 F# 中的async
块之外),没有(简单)方法可以实现真正的非阻塞执行。如果您想使用 F# 来获得异步工作流程的优势,那么最好的选择是在 F# 中实现操作,然后使用
Async.StartAsTask
将它们公开给 C#(这为您提供了Task< ;T>
C# 可以轻松使用)。类似这样的事情:如果您不想使用 F#(至少对于异步计算的实现),那么异步工作流程将无法帮助您。您可以使用
Task
、BackgroundWorker
或其他 C# 技术实现类似的功能(但您将失去在不阻塞线程的情况下轻松运行操作的能力)。To get the benefits of F# asynchronous workflow, you have to actually write the asynchronous computation in F#. The code you're trying to write will not work (i.e. it may run, but won't be useful).
When you're writing asynchronous computations in F#, you can make asynchronous calls using
let!
anddo!
. This allows you to use other primitive non-blocking computations. For example, you can useAsync.Sleep
instead ofThread.Sleep
.You can only use asynchronous operations inside the
async
block and it relies on the way how F# compiler handlesdo!
andlet!
. There is no (easy) way to get real non-blocking execution for code that is written in sequential way (e.g. in C# or outside ofasync
block in F#).If you want to use F# to get the benefits of asynchronous workflows, then the best option is to implement the operations in F# and then expose them to C# using
Async.StartAsTask
(which gives youTask<T>
that C# can easily use). Something like this:If you don't want to use F# (at least for the implementation of your async computations), then asynchronous workflows won't help you. You can implement similar thing using
Task
,BackgroundWorker
or other C# technologies (but you'll loose the ability to run operations easily without blocking threads).