2016-12-21 16 views
2

我建立包含一个F#文件的项目和构建过程中存在的39行错误:这种表达预计将有型异步<'a>但这里已经输入的DispatcherOperation

这表达预计将有型异步<“一>但这里有类型的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 

有谁知道为什么这个错误即将到来,如何解决?

回答

4

错误消息说明了这一切:Dispatcher.InvokeAsync返回DispatcherOperationAsync.StartWithContinuations预计Async

您可以等待DispatcherOperation.Task

Async.StartWithContinuations(
    disp.InvokeAsync((fun() -> callback.Invoke(context))).Task |> Async.AwaitTask, 
    ignore, 
    error, 
    cancel, 
    ct) 

注意包裹的表达async不会自动使异步和包装已经异步流,而不等待两次甚至可能不执行内部异步可言:

let print = async { printfn "Can we observe this?" } 

async { return print } |> Async.RunSynchronously // nothing printed 
async { return! print } |> Async.RunSynchronously // prints message 

所以这不是异步:

Async.StartWithContinuations(
    async { disp.Invoke((fun() -> callback.Invoke(context))) }, 
    ignore, 
    error, 
    cancel, 
    ct) 

,这甚至可能没有调用回调函数(取决于InvokeAsync实施,Task s的通常隐含虽然起步):

Async.StartWithContinuations(
    async { disp.InvokeAsync((fun() -> callback.Invoke(context))) }, 
    ignore, 
    error, 
    cancel, 
    ct) 

在顶部,回调(通常是成功的一个,在这里:ignore)可以被称为之前内部回调返回。

+0

为什么要在这里使用'Async.AwaitIAsyncResult'而不是'Async.AwaitTask'?后者更清晰(大多数人不知道'IAsyncResult'是什么),并且可能会更有效率。 – svick

+0

在'async'内使用'Invoke'不会使代码异步。你可能直接调用'disp.Invoke()'。 – svick

+0

@svick谢谢,我'修复'了'Async.AwaitTask'。第二个例子是为了“让类型匹配”,但我应该正确解释。 – CaringDev

1

我已经得到了我的问题的解决方案。

方法“StartWithContinuations”具有类型Async <'T>的第一个参数“计算”,所以我用async {}包含了第一个参数。

let disp = Application.Current.Dispatcher     
      Async.StartWithContinuations(
       async {disp.InvokeAsync((fun() -> callback.Invoke(context)))}, 
       ignore, 
       error, 
       cancel, 
       ct 
      ) 
     ) 
+0

这可能不会做你想要的......虽然好主意,启发编辑我的答案。 – CaringDev

+0

这将有效地忽略'InvokeAsync'的结果,因此延续将不会在正确的时间执行。 – svick

相关问题