gpt4 book ai didi

.net - Task.WaitAll 的线程局部对象

转载 作者:行者123 更新时间:2023-12-02 07:09:08 35 4
gpt4 key购买 nike

我有少量任务,我想使用 Task.WaitAll 并行运行它们。这是我现在拥有的:

type System.Threading.Tasks.Task with
static member WaitAll(ts) =
Task.WaitAll [| for t in ts -> t :> Task |]

let processf p fs =
let rand = Random ()
let ts = fs |> Array.map (fun f -> Task.Factory.StartNew(fun () -> p(f, rand)))
Task.WaitAll(ts)
ts |> Array.map (fun t -> t.Result)

问题是 Random 不是线程安全的(选择 Random 类只是为了说明目的)。如何为每个线程创建一个对象而不是为每个 Task 创建一个对象,这很浪费?

编辑:

像 Brian 和 Daniel 的建议那样使用 ThreadStatic 是一个很好的方法,尤其是对于工厂类。但是,我更喜欢 Reed 和 Tomas 建议的 ThreadLocal,因为它看起来更简单。我同意使用主 Random 有点过于复杂。以下是我保留以供将来引用的混合解决方案:

let processf p fs =
use localRand = new ThreadLocal<_>(
fun() -> Random(Thread.CurrentThread.ManagedThreadId))
let ts = fs |> Array.map (fun f ->
Task.Factory.StartNew(fun () -> p(f, localRand.Value)))
Task.WaitAll(ts)
ts |> Array.map (fun t -> t.Result)

最佳答案

您可以将特定于线程的状态放入工厂类中并将其标记为ThreadStatic

type PerThread =

[<ThreadStatic; DefaultValue>]
static val mutable private random : Random

static member Random =
match PerThread.random with
| null -> PerThread.random <- Random(Thread.CurrentThread.ManagedThreadId)
| _ -> ()
PerThread.random

然后你可以这样做:

let process p fs =
let ts = fs |> Array.map (fun f ->
Task.Factory.StartNew(fun () -> p(f, PerThread.Random)))
Task.WaitAll(ts)
ts |> Array.map (fun (t: Task) -> t.Result)

关于.net - Task.WaitAll 的线程局部对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7842033/

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