Ruby / Rails超时与线程 - 如何等待一段时间然后重新加入

Posted

技术标签:

【中文标题】Ruby / Rails超时与线程 - 如何等待一段时间然后重新加入【英文标题】:Ruby / Rails Timeout with threads - how to wait a while then rejoin later 【发布时间】:2022-01-12 12:34:32 【问题描述】:

我正在尝试在线程中运行一个进程,如果它花费的时间超过 x 秒,则重定向到等待页面,然后执行 ajax 刷新

begin
    Timeout::timeout(10) do
        t = Thread.new do
            begin
                output = do_work
                session[:result] = "done"
            rescue Exception => e
                session[:result] = "exception"
            end
        end
        t.join
    end
    if session[:result] = "done"
        redirect_to :done
    else
        redirect_back fallback_location: :root, notice: 'Unable to process request, please try again.'
    end
rescue Exception => e
    if e.message == "execution expired"
        # this means the timeout fired, so send them to waiting
        redirect_to waiting_path
    else
        redirect_back fallback_location: :root, notice: 'Unable to process request, please try again.'
    end
end

然后,在等待中,检查结果

def waiting
    # session[:result] never updates
end

我做错了什么?我希望如果异常触发,线程会存活下来,正如这个简单的实验所证明的那样:

begin
    Timeout::timeout(1) do
        t = Thread.new do
            sleep(5)
            puts "done!"
        end
        t.join
    end
rescue Exception => e
    if e.message == "execution expired"
        # this means the timeout fired, so send them to waiting
        puts "expired!"
    end
end

上面的代码工作正常,5秒后线程完成并显示输出。

这是因为您无法在线程中设置会话,还是类似的原因?

感谢您的帮助, 凯文

【问题讨论】:

session 是指session cookie 吗? 线程块代码是否出现异常?如果是这样,则不会引发异常“执行过期”。 【参考方案1】:

您可以尝试将当前绑定作为参数传递给线程:

Thread.new(binding) do 
    thread_session = eval("session", binding)
end

注意:我建议使用 DelayedJob 更好的方式来处理从用户请求中分离出来的长时间运行的进程?

【讨论】:

以上是关于Ruby / Rails超时与线程 - 如何等待一段时间然后重新加入的主要内容,如果未能解决你的问题,请参考以下文章

如何解决高并发,连接等待超时的异常

使用 Capistrano 将 Ruby on Rails 应用程序部署到 Windows Azure VM 时出现超时错误

多线程设置线程超时思路

如何在 C# 中等待单个事件,带有超时和取消

在进行数据库调用的线程中使用 ruby​​ 超时

如何等待超时的承诺?