【发布时间】:2013-01-03 00:22:29
【问题描述】:
我正在尝试在 Rails 启动时创建一个线程,该线程将在应用程序的整个生命周期中运行。奇怪的是,我已经使用我正在运行的另一个线程进行了此操作。我复制了该(工作)代码并将其用作新线程的新代码的样板。但线程不会启动。
- 代码在 config/initializers 中(这是正确的位置吗?)。
- 文件以“z_...”开头命名,以确保它最后运行。
- Rails 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”,这样就解决了问题。但我仍然想知道是什么导致了问题,以及什么是“非黑客”解决方案。由于某种原因,此代码运行时数据库尚未准备好。我的初始化代码是不是放错地方了?
【问题讨论】:
-
这可能是您的代码的问题。如果您复制和粘贴内容,很有可能您使用了相同的类名,并且以某种方式确实覆盖了其他线程代码或类似的内容。
-
我已经检查了每一寸代码(没有太多 - 大约一页)。除了基本结构之外,没有任何共同点(变量名、类名等)。我什至删除了其他代码作为测试,但这无济于事。
-
我很好奇你为什么要这样做?假设是因为您希望在后台进程中运行某些东西。如果是这样,你为什么不看一下delayed_job、resque 或sidekiq?
-
我不想为一个非常简单的任务陷入复杂或繁重的任务,该任务可以在半页中编码,每天只需要运行一次('sleep 5 seconds ' 上面用于测试)。
-
然后使用带有纯文件的 cron 作业。线程很繁重,在这里自找麻烦
标签: ruby-on-rails multithreading configuration initialization