如何在 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 在同一线程上执行。
我还没有真正尝试过,但我认为这就是正在发生的事情。
我试过以下方法:
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 在同一线程上执行。
我还没有真正尝试过,但我认为这就是正在发生的事情。