I am building a project which contains a F# file and during build there is an error on line 39:
This expression was expected to have type Async<'a> but here has type DispatcherOperation
open System
open System.Collections.Generic
open System.Collections.ObjectModel
open System.Linq
open System.Net
open System.Reactive.Disposables
open System.Runtime.CompilerServices
open System.Threading
open System.Windows
open System.Windows.Threading
open Microsoft.Practices.Unity
type IActivityContext<'TResult> = interface
abstract container: IUnityContainer
abstract Success: result:'TResult -> unit
abstract Error: error:Exception -> unit
abstract Cancel: unit -> unit
abstract RegisterCancellationCallback: callback:Action->IDisposable
end
[<Extension>]
type ActivityExtensions private() = class
[<Extension>]
static member StartViewActivity<'TResult>(container: IUnityContainer, callback: Action<IActivityContext<'TResult>>)= async{
let! ct = Async.CancellationToken
return! Async.FromContinuations(fun (success, error, cancel) ->
let context = {
new IActivityContext<'TResult> with
member this.container = container
member this.Success(result:'TResult) = success(result)
member this.Error(err:Exception) = error(err)
member this.Cancel() = cancel(new OperationCanceledException())
member this.RegisterCancellationCallback(callback: Action) =
ct.Register(callback) :> IDisposable
}
let disp = Application.Current.Dispatcher
Async.StartWithContinuations(
(* ERROR -> *) disp.InvokeAsync((fun() -> callback.Invoke(context))),
(fun()->()),
error,
cancel,
ct
)
)
}
end
Does anyone know why this error is coming and what is the solution?
I have got the solution of my problem.
Method "StartWithContinuations" has first parameter "computation" of type Async<'T> so i have enclosed first parameter with async{}.
let disp = Application.Current.Dispatcher
Async.StartWithContinuations(
async {disp.InvokeAsync((fun() -> callback.Invoke(context)))},
ignore,
error,
cancel,
ct
)
)
The error message says it all: Dispatcher.InvokeAsync
returns a DispatcherOperation
whereas Async.StartWithContinuations
expects an Async
.
You can await the DispatcherOperation.Task
:
Async.StartWithContinuations(
disp.InvokeAsync((fun() -> callback.Invoke(context))).Task |> Async.AwaitTask,
ignore,
error,
cancel,
ct)
Note that wrapping an expression with async
will not automatically make it asynchronous and wrapping an already async flow without awaiting twice might not even execute the inner async at all:
let print = async { printfn "Can we observe this?" }
async { return print } |> Async.RunSynchronously // nothing printed
async { return! print } |> Async.RunSynchronously // prints message
So this is not asynchronous:
Async.StartWithContinuations(
async { disp.Invoke((fun() -> callback.Invoke(context))) },
ignore,
error,
cancel,
ct)
and this might not even invoke the callback (depending on InvokeAsync
implementation, Task
s are usually implicitly started though):
Async.StartWithContinuations(
async { disp.InvokeAsync((fun() -> callback.Invoke(context))) },
ignore,
error,
cancel,
ct)
On top, callbacks (typically the success one, here: ignore
) might be called before the inner callback returns.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With