我有以下线程间通信问题的简单示例:我想在后台线程中运行任意“随时”算法。任何时间算法都会以增量方式执行某些结果类型的计算T
,即它偶尔会产生更新、更精确的结果。用 Nim 的说法,它们可能最好用迭代器来表示。在主线程中,我现在想将每个迭代器包装在自己的线程中,并可以查询线程以获取诸如“是否有可用的新值”或“当前计算结果是什么”之类的内容。
由于我不熟悉 Nim 的并发概念,我很难实现所需的线程间通信。我的想法是使用 aTChannel
进行通信。根据这个论坛帖子, aTChannel
不能与 结合使用,spawn
但需要使用createThread
。我设法得到以下编译和运行:
import os, threadpool
proc spawnBackgroundJob[T](f: iterator (): T): TChannel[T] =
type Args = tuple[iter: iterator (): T, channel: ptr TChannel[T]]
# I think I have to wrap the iterator to pass it to createThread
proc threadFunc(args: Args) {.thread.} =
echo "Thread is starting"
let iter = args.iter
var channel = args.channel[]
for i in iter():
echo "Sending ", i
channel.send(i)
var thread: TThread[Args]
var channel: TChannel[T]
channel.open()
let args = (f, channel.addr)
createThread(thread, threadFunc, args)
result = channel
# example use in some main thread:
iterator test(): int {.closure.} =
sleep(500)
yield 1
sleep(500)
yield 2
var channel = spawnBackgroundJob[int](test)
for i in 0 .. 10:
sleep(200)
echo channel.peek()
echo "Finished"
不幸的是,这没有预期的行为,即我从未在主线程中收到任何东西。我在 IRC 上被告知问题是我不使用全局变量。但即使经过很长时间的思考,我也不明白为什么会失败,也没有办法解决它。问题是我不能简单地使变量thread
和channel
全局变量,因为它们取决于类型T
。我还想避免将其限制为仅运行一个任何时间算法(或其他一些固定数字 N)。我还被告知该方法总体上没有意义,所以也许我只是错过了这个问题有一个完全不同的解决方案?