如何在 F# 中使用 backgroundTask 计算表达式

how to use the backgroundTask computation expression in F#

我试过以下方法:

let o = Object()
let print message =
    // lock to make the console output cleaner
    lock o (fun _ -> printfn $"{message}")
    
let doAndWait name =
    print $"start {name}"
    Thread.Sleep(TimeSpan.FromSeconds(1))
    print $"end {name}"
    1

let a = backgroundTask { return doAndWait "A" }
let b = backgroundTask { return doAndWait "B" }

print "waiting for nothing"
Thread.Sleep(TimeSpan.FromSeconds(3))
print $"finished: {r.Result}"
let c = a.Result + b.Result
printfn $"finished: {c}"

我的期望显然是错误的,我的期望是后台任务将在线程池上启动,我可以稍后收集结果。

实际上,先执行'a',然后执行'b',然后执行'wait for nothing'代码。所以执行纯粹是顺序的。

我期待这样的行为:

let x = async { return doAndWait "X" }
let y = async { return doAndWait "Y" }

let r =
    async {
        let! x' = x
        let! y' = y
        return x' + y'
    }
    |> Async.StartAsTask

print "waiting for nothing"
Thread.Sleep(TimeSpan.FromSeconds(3))
print $"finished: {r.Result}"

所以,我无法理解 'backgroundTask' CE 是什么。考虑到索引的“backgroundTask”字符串的数量,google 搜索是徒劳的 :D

我正在这里查看文档:

https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/task-expressions#background-tasks

它说

A background task ignores any SynchronizationContext.Current in the following sense: if started on a thread with non-null SynchronizationContext.Current, it switches to a background thread in the thread pool using Task.Run. If started on a thread with null SynchronizationContext.Current, it executes on that same thread.

在 GUI 应用程序中,SynchronizationContext.Current 将是 non-null,因此在这种情况下,backgroundTask 将切换到线程池。由于您在控制台应用程序中,SynchronizationContext.Current 将为空,因此 backgroundTask 在同一线程上执行。

我还没有真正尝试过,但我认为这就是正在发生的事情。