从C#调用并等待F#异步方法

Tho*_*mas 1 c# f# asynchronous

我在F#中有这个:

type RuleStore() =

    ...
    static member LoadAsync : Async<RulesStore> =
        async {
            let! r = Startup.States.GetAsStringAsync("rules") |> Async.AwaitTask

            return
                if String.IsNullOrEmpty r then
                    new RulesStore()
                else
                    JsonConvert.DeserializeObject<RulesStore>(r);
        }
Run Code Online (Sandbox Code Playgroud)

我试图从C#调用它,但是语法似乎不起作用。

NewRules =等待Rules.RulesStore.LoadAsync();

我得到的错误是:

Core.cs(29,38):[CS1955]不可发音的成员'Rules.RulesStore.LoadAsync'不能像方法一样使用。

我不太了解,因为我觉得LoadAsync只是一个静态方法。

Tom*_*cek 5

您不能打电话有两个原因await Rules.RulesStore.LoadAsync()

首先,您的代码实际上是定义一个仅获取属性。在F#中,用于定义仅获取属性的语法与用于定义方法的语法非常相似:

static member LoadAsync : Async<RulesStore> =   // Defines a get-only property
static member LoadAsync() : Async<RulesStore> = // Defines a method
Run Code Online (Sandbox Code Playgroud)

您可以使用get-only属性和call await Rules.RulesStore.LoadAsync,但这对于C#调用者来说似乎很奇怪,因此方法似乎是一个更好的选择。

其次,您的代码正在返回,Async<'T>但是C#Task<'T>改为使用type。您可以在C#中将“异步”转换为“任务”,但是在F#端这样做更容易。为此,您需要更改类型并添加Async.StartAsTask到末尾(作为个人风格偏好,我也要在return里面if,但这只是因为我认为它看起来更好):

type RuleStore() =

    ...
    static member LoadAsync : Task<RulesStore> =
        async {
            let! r = Startup.States.GetAsStringAsync("rules") |> Async.AwaitTask
            if String.IsNullOrEmpty r then
                return new RulesStore()
            else
                return JsonConvert.DeserializeObject<RulesStore>(r);
        } |> Async.StartAsTask
Run Code Online (Sandbox Code Playgroud)