.net - 跨多个线程管理状态

标签 .net multithreading f# thread-safety

我有一个带有一堆序列的 F# 类。该类包含一个简单的 next() 方法,该方法返回当前序列中的下一个元素。如果当前序列的所有元素都已返回,则它将转移到下一个序列。该类包含一个指针,该指针是序列中的下一个元素以及它从哪个序列返回。

我目前仅限于公开 next() 方法。

一些上游类将在不同线程之间使用我的类(相同的对象实例)。这将使点不同步,因为多个线程都应该从头开始。我知道这并不理想,但这是我目前必须处理的问题。

示例:

线程1 next():返回elem。 A 线程1 next():返回elem。乙 线程2 next():返回elem。 A 线程1 next():返回elem。 C 线程2 next():返回elem。乙

有没有办法跟踪每个线程的指针?

我一直在考虑使用 Threading.Thread.CurrentThread.ManagedThreadId 作为 Map 中的键,然后返回指针(并相应地更新它)。我有点担心这个 Map 的线程安全性以及两个线程是否同时更新其状态。

我希望有人能为我提供一些关于如何让它发挥作用的想法。

最佳答案

这可以通过使用MailboxProcessor来管理状态,然后使用一个类从使用者抽象MailboxProcessor来完成。如果您跨多个线程共享一个实例,它们将以线程安全的方式看到彼此的更新。如果您为每个线程使用专用实例,它们将只能看到自己的更新。其代码如下所示:

// Add whatever other commands you need
type private SequenceMessage = Next of AsyncReplyChannel<int>

type IntSequence() =
    let agent = MailboxProcessor<SequenceMessage>.Start
                <| fun inbox ->
                    let rec loop state =
                        async {
                            let! message = inbox.Receive()
                            // Add other matches as requried
                            match message with
                            | Next channel -> 
                                let newState = state + 1
                                channel.Reply(newState)
                                return! loop newState
                        }
                    loop 0

    let next () =
        agent.PostAndReply <| fun reply -> Next reply

    let asyncNext () =
        agent.PostAndAsyncReply <| fun reply -> Next reply

    member __.Next () = next ()
    member __.AsyncNext () = asyncNext ()

然后,要以每个线程都能看到来自其他线程的更新的方式使用它,您将执行与此等效的操作:

// To share state across multiple threads, use the same instance
let sequence = IntSequence()
[1..10]
|> List.map (fun _ -> sequence.AsyncNext())
|> Async.Parallel
|> Async.RunSynchronously
|> Array.iter (fun i -> printfn "%d" i)

打印内容:

1
2
3
4
5
6
7
8
9
10

要以每个线程仅看到自己的更新的方式使用它,您只需将前面的示例更改为如下所示:

// To use a dedicate state for each thread, create a new instance
[1..10]
|> List.map (fun _ -> IntSequence())
|> List.map (fun sequence -> sequence.AsyncNext())
|> Async.Parallel
|> Async.RunSynchronously
|> Array.iter (fun i -> printfn "%d" i)

打印内容:

1
1
1
1
1
1
1
1
1
1

关于.net - 跨多个线程管理状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50191069/

相关文章:

java - 将 RequestAttributes 传递给新线程后, session 丢失

java - 如果数据频繁变化,应该使用什么类型的java缓存?

unit-testing - 在 F# Foq 中模拟非标准事件

f# - FS0039 : The namespace is not defined

c# - UTF8 在 Excel 中不起作用

c# - 解决 .NET Core 启动中的 Hangfire 依赖项/HttpContext

java - 从多个远程资源读取数据

c# - xUnit v1 测试出现在 xUnit GUI (xunit.gui.clr4.exe) 但不是 VS 2012 测试资源管理器

.net - VS 2010 性能资源管理器

c# - 从 .NET 正则表达式对象获取命名组子模式