Xamarin F到C异步调用:正确的现代方式
我试图从Xamarin中的F代码同步调用C#Async函数。原始C#代码如下所示(这是Plugin.BLE目标设备服务发现): 如果我使用的是推荐的F#primitiveXamarin F到C异步调用:正确的现代方式,xamarin,f#,c#-to-f#,f#-async,Xamarin,F#,C# To F#,F# Async,我试图从Xamarin中的F代码同步调用C#Async函数。原始C#代码如下所示(这是Plugin.BLE目标设备服务发现): 如果我使用的是推荐的F#primitive module Async = let inline AwaitPlainTask (task: Task) = task.ContinueWith(fun t -> ()) |> Async.AwaitTask 以下代码: async { let! ser
module Async =
let inline AwaitPlainTask (task: Task) =
task.ContinueWith(fun t -> ())
|> Async.AwaitTask
以下代码:
async {
let! service = Async.AwaitPlainTask <|d.GetServiceAsync(serviceGuid)
let! characteristic = Async.AwaitPlainTask <|service.GetCharacteristicAsync(characteristicGuid)
...
serviceTask.Result始终为空。同样的结果(null)也会发生在
let! service = d.GetServiceAsync(serviceGuid) |> Async.AwaitTask
也是。C代码正在工作,所以基本上问题在于如何从F调用它。我想我在这里误解了什么,正确的方法是什么
注:这不是问题的重复,因为这可能已经过时,不再有效(至少在Xamarin上是如此)。您在这里使用的函数
等待任务,看起来它是一个处理任务的便利函数。但是,在F#异步
计算表达式中有一种处理任务
的标准方法。您应该使用Async.AwaitTask
,以及let代码>,如下所示:
async {
// Removing back-pipes as they are often more confusing that useful
let! service = d.GetServiceAsync(serviceGuid) |> Async.AwaitTask
let! characteristic = service.GetCharacteristicAsync(characteristicGuid) |> Async.AwaitTask
...
否则,你所做的就是将Task
转换为Task
并尝试等待它:
var result = await ((Task)d.GetServiceAsync(serviceGuid))
它不会在C#中编译,但是在F#中我们有单元
类型,它实际上非常方便,因为您不需要大量的类型和泛型代码重载
还值得注意的是,您可能可以删除awaitplantask
,因为它现在是自F#4.0以来内置的Async.AwaitTask
的重载,例如:
let waitOneSecond () = async {
// Use do! not let! when you aren't using the result
do! Task.Delay(1000) |> Async.AwaitTask
}
let! service = d.GetServiceAsync(serviceGuid) |> Async.AwaitTask
let service = service |> Option.ofObj
match service with
| Some s -> let! characteristic = s.GetCharacteristicAsync(characteristicGuid) |> Async.AwaitTask
()
| None -> ()
我已经看过了Plugin.BLE
,它看起来像是等待GetServiceAsync
可以返回null
,正如您所说,这是库的设计
为了处理这个问题,我们可以将结果包装成一个选项
类型,并将其作为一种安全的方式在之后访问它。例如:
let waitOneSecond () = async {
// Use do! not let! when you aren't using the result
do! Task.Delay(1000) |> Async.AwaitTask
}
let! service = d.GetServiceAsync(serviceGuid) |> Async.AwaitTask
let service = service |> Option.ofObj
match service with
| Some s -> let! characteristic = s.GetCharacteristicAsync(characteristicGuid) |> Async.AwaitTask
()
| None -> ()
正如我在问题中提到的,let!service=d.GetServiceAsync(serviceGuid)|>Async.AwaitTask
为服务返回null。(C#相同情况下的代码有效)@Darkkey如果这个答案有用,请记住标记:)@JuniorJiang MSFT这个答案没有帮助不幸的是,它表明了我已经尝试过的方式(包括在问题中)。正如我在上面的评论中提到的,它不起作用(服务变为null)。这不是库的问题,因为等效的C代码正在工作。啊,我理解。我会在几个小时内更新我的答案。