gpt4 book ai didi

multithreading - F# 事件的线程安全引发

转载 作者:行者123 更新时间:2023-12-04 08:26:27 25 4
gpt4 key购买 nike

我正在尝试执行 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# 事件做同样的事情,卡住锁内的订阅者列表但在锁外调用它?

最佳答案

这在 F# 中不是那么简单,因为 Event<_>不公开其订阅者列表,该列表由 Add 突变/Remove .

您可以通过为每个处理程序创建一个新事件来避免这种突变。

let mutable completed = Event<_>()

//...

let ev = Event<_>()
let iev = ev.Publish
iev.Add(completed.Trigger)
iev.Add(callBack.Invoke)
completed <- ev

//...

let ev = lock locker <| fun () ->
computedValue := Some result
completed
ev.Trigger(result)

关于multithreading - F# 事件的线程安全引发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15068010/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com