我正在尝试在 Rails 启动时创建一个线程,该线程将在应用程序的整个生命周期中运行。奇怪的是,我已经使用我正在运行的另一个线程进行了此操作。我复制了该(工作)代码并将其用作新线程的新代码的样板。但是线程不会启动。
- 代码在 config/initializers 中(这是正确的地方吗?)。
- 文件以“z_...”开头命名,以确保它最后运行。
- 导轨 3.2.6
下面是代码的一般结构:
class Blah
def self.the_thread
The_Model.transaction do
# do some database stuff
# ...
end
TheThread = Thread.new do
while true do
the_thread
sleep 5.seconds
end
end
end
打开 Rails 控制台并检查 Blah::TheThread 会发现一个似乎从未运行过的死线程。类的声明和方法中似乎没有任何错误,因为我可以在打开 rails 控制台时运行该方法并且它工作得很好。此外,如果我在 Rails 控制台中手动输入生成线程的确切代码(TheThread = Thread new do ...),它工作得很好(每 5 秒唤醒一次,做它的事情,再次休眠)。
再一次,奇怪的是,这个在 Rails 中生成简单线程的确切样板文件在这个完全相同的应用程序中对我有用。
如果有人对我认为是一个奇怪的问题有一些可能的见解,我会全神贯注。
谢谢。
编辑:新信息 - 我刚刚注释掉了事务调用(和匹配结束),它工作正常。我不知道交易可能会干扰什么。我删除了我的其他自定义初始化脚本,目录中唯一的其他脚本要么是默认脚本,要么是属于 devise 的脚本。我仔细阅读了它们,并没有看到任何交易正在进行。
更多新信息。我在线程代码的末尾添加了“TheThread.abort_on_exception = true”。当我启动 rails 时,我现在得到一个异常“ArgumentError:在关闭的数据库上调用准备:回滚事务(ActiveRecord::StatementInvalid)”。错误发生在 sqlite3 gem 中。我有 sqlite3 gem 版本 1.3.6 和 sqlite-ruby gem 版本 1.3.3。我用谷歌搜索了这个错误,发现几个帖子抱怨同样的错误,但没有看到任何解决方案。
我不再认为这是一个线程问题,而是一个数据库问题,但是来不及改变这篇文章的标题。
这只是在:我在线程代码的顶部(就在它进入while循环之前)放置了一个'sleep 15.seconds',这样就解决了问题。但我仍然想知道是什么导致了问题,以及什么是“非黑客”解决方案。由于某种原因,此代码运行时数据库尚未准备好。我的初始化代码只是在错误的地方吗?