Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 跨多个线程管理状态_.net_Multithreading_F#_Thread Safety - Fatal编程技术网

.net 跨多个线程管理状态

.net 跨多个线程管理状态,.net,multithreading,f#,thread-safety,.net,Multithreading,F#,Thread Safety,我有一个F#类,有一系列序列。该类包含一个简单的next()方法,该方法返回当前序列中的下一个元素。如果当前序列的所有元素都已返回,它将切换到下一个序列。该类包含一个指针,该指针是序列中的下一个元素,它从哪个序列返回 我目前仅限于公开next()方法 一些上游类将在不同线程之间使用我的类(相同的对象实例)。这将使点失去同步,因为多个线程都应该从头开始。我知道这并不理想,但这是我目前必须处理的问题 例如: 线程1 next():返回元素。A. 线程1 next():返回元素。B 线程2 next

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

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

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

例如:


线程1 next():返回元素。A.
线程1 next():返回元素。B
线程2 next():返回元素。A.
线程1 next():返回元素。C
线程2 next():返回元素。B

有没有一种方法可以跟踪每个线程的指针

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


我希望有人能为我提供一些如何让它工作的想法。

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

// 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 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
2
3
4
5
6
7
8
9
10
1
1
1
1
1
1
1
1
1
1
要以每个线程只看到自己更新的方式使用它,您只需将前面的示例更改为如下内容:

// 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 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
2
3
4
5
6
7
8
9
10
1
1
1
1
1
1
1
1
1
1