我正在尝试进行 F# 异步计算,该计算在准备好时调用 C# 回调。代码如下:
type Worker() =
let locker = obj()
let computedValue = ref None
let started = ref false
let completed = Event<_>()
let doNothing() = ()
member x.Compute(callBack:Action<_>) =
let workAlreadyStarted, action =
lock locker (fun () ->
match !computedValue with
| Some value ->
true, (fun () -> callBack.Invoke value)
| None ->
completed.Publish.Add callBack.Invoke
if !started then
true, doNothing
else
started := true
false, doNothing)
action()
if not workAlreadyStartedthen
async {
// heavy computation to calc result
let result = "result"
lock locker (fun () ->
computedValue := Some result
completed.Trigger result)
} |> Async.Start
但是有一个问题,我想在锁外触发完成的事件,但我想确保触发是线程安全的(实际上,在这个小例子中,我可以在锁外触发事件,因为我不知道其他人将订阅它,但并非总是如此)。
在 C# 事件中,这很容易实现:
object locker = new object();
event Action<string> MyEvent;
void Raise()
{
Action<string> myEventCache;
lock (locker)
{
myEventCache = MyEvent;
}
if (myEventCache != null)
{
myEventCache("result");
}
}
如何对 F# 事件执行等效操作,冻结锁内的订阅者列表但在锁外调用它?