Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

This expression was expected to have type Async<'a> but here has type DispatcherOperation

Tags:

async-await

f#

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?

like image 761
Naveen Verma Avatar asked Dec 21 '16 09:12

Naveen Verma


2 Answers

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
            )
        )
like image 43
Naveen Verma Avatar answered Oct 07 '22 19:10

Naveen Verma


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, Tasks 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.

like image 77
CaringDev Avatar answered Oct 07 '22 21:10

CaringDev