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()
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.Sleepinstead ofThread.Sleep.You can only use asynchronous operations inside the
asyncblock 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 ofasyncblock 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,BackgroundWorkeror other C# technologies (but you’ll loose the ability to run operations easily without blocking threads).