Ruby   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了ruby块内的赛璐id异步不起作用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
试图在我的工作实例上实现Celluloid异步似乎表现出奇怪的行为.

这里我的代码看起来

class Indefinite
    include Celluloid

      def run!
         loop do 
           [1].each do |i|
             async.on_BACkground
           end
         end
      end 


       def on_BACkground
         puts "Running in BACkground" 
       end
   end

   Indefinite.new.run!

但是当我运行上面的代码,我从来没有看到放置“在后台运行”

但是,如果我睡觉,代码似乎工作.

class Indefinite
   include Celluloid

    def run! 
      loop do 
        [1].each do |i|
          async.on_BACkground
        end
        sleep 0.5
      end 
    end


   def on_BACkground
     puts "Running in BACkground" 
   end
 end

 Indefinite.new.run!

任何想法?为什么在上述两种情况下有这样的区别.

谢谢.

解决方法

你的主要循环是主角/应用程序的线程.

你所有的程序正在做的是产生后台进程,但从不运行它们.你需要在循环中的睡眠才能让背景线程得到注意.

通过一个无条件的循环来产生无限的后台进程通常不是一个好主意,就像你在这里一样.应该有一个延迟或条件语句放在那里…否则你只有一个无限循环产生永远不会被调用的东西.

想像这样:如果你把循环放在你的循环中,而你没有看到在后台运行,你会看到循环一遍又一遍.

方法#1:使用每个或更多的块.

解决这个问题的最好方法是不要在循环中使用睡眠,而是使用一个或多个块,如下所示:

every(0.1) {
    on_BACkground
}

或者最重要的是,如果要确保进程在运行前完全运行,请再次运行:

def run_method
    @running ||= false
    unless @running
        @running = true
        on_BACkground
        @running = false
    end
    after(0.1) { run_method }
 end

使用循环不是异步的好主意,除非有某种流量控制完成,或者使用@ server.accept等阻塞过程,否则只会将100%的CPU内核没有任何理由.

便说一句,你也可以使用Now_and_every以及now_and_after,这样也可以立即运行该块,然后在你想要的时间后再运行一次.

使用每一个都显示在这个要点中:

> https://gist.github.com/digitalextremist/686f42e58a58b743142b

理想情况,在我看来:

这是一个粗略但立即可用的示例:

> https://gist.github.com/digitalextremist/12fc824c6a4dbd94a9df

require 'celluloid/current'

class Indefinite
  include Celluloid

  INTERVAL = 0.5
  ONE_AT_A_TIME = true

  def self.run!
    puts "000a InstantiaTing."
    indefinite = new
    indefinite.run
    puts "000b Running forever:"
    sleep
  end

  def initialize
    puts "001a Initializing."
    @mutex = Mutex.new if ONE_AT_A_TIME
    @running = false
    puts "001b Interval: #{INTERVAL}"
  end

  def run
    puts "002a Running."
    unless ONE_AT_A_TIME && @running
      if ONE_AT_A_TIME
        @mutex.synchronize {
          puts "002b Inside lock."
          @running = true
          on_BACkground
          @running = false
        }
      else
        puts "002b Without lock."
        on_BACkground
      end
    end
    puts "002c SetTing new timer."
    after(INTERVAL) { run }
  end


  def on_BACkground
    if ONE_AT_A_TIME
      puts "003 Running BACkground processor in foreground."
    else
      puts "003 Running in BACkground"
    end
  end
end

Indefinite.run!
puts "004 End of application."

这将是其输出,如果ONE_AT_A_TIME为真:

000a InstantiaTing.
001a Initializing.
001b Interval: 0.5
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.
000b Running forever:
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.
002a Running.
002b Inside lock.
003 Running BACkground processor in foreground.
002c SetTing new timer.

如果ONE_AT_A_TIME为假,这将是其输出:

000a InstantiaTing.
001a Initializing.
001b Interval: 0.5
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.
000b Running forever:
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.
002a Running.
002b Without lock.
003 Running in BACkground
002c SetTing new timer.

您需要比“线程”更多地“发送”,以正确发出任务并保留范围和状态,而不是在线程/ actors之间发出命令,这是每个和每个块提供的内容.除此之外,无论哪种方式,即使您没有Global Interpreter Lock来处理这种做法也是一个很好的做法,因为在您的示例中,您似乎并不喜欢处理阻止进程.如果你有一个阻塞过程,那么一切都有一个无限循环.但是,由于您只是在处理之前最终产生无限数量的后台任务,所以您需要像开始使用您的问题一样使用睡眠,或者使用完全不同的策略,然后使用每一个Celloloid本身如何鼓励您在处理任何类型的插座上的数据时进行操作.

方法#2:使用递归方法调用.

这刚刚出现在Google集团.下面的示例代码实际上将允许执行其他任务,即使它是一个无限循环.

> https://groups.google.com/forum/#!topic/celluloid-ruby/xmkdrMQBGbY

这种方法不太可取,因为它可能会有更多的开销,产生一系列的纤维.

def work
    # ...
    async.work
end

问题2:线程与光纤行为.

第二个问题是为什么下面的工作:循环{Thread.new {puts“Hello”}}

这产生了无数个进程线程,由线程直接管理.即使您正在使用RVM中的全局解释器锁定,这仅意味着不会使用绿色线程,这些线程由操作系统本身提供,而是由进程本身处理.该进程的CPU调度程序会毫不犹豫地运行每个线程本身.在这个例子的情况下,线程运行非常快,然后死亡.

与异步任务相比,使用了光纤.所以发生的是这样的,在默认情况下:

>进程启动.
>演员实例化.
方法调用调用循环.
循环调用异步方法.
> async方法将任务添加到邮箱.
>邮箱不被调用,循环继续.
>另一个异步任务被添加到邮箱.
>这继续无限.

大佬总结

以上是大佬教程为你收集整理的ruby块内的赛璐id异步不起作用全部内容,希望文章能够帮你解决ruby块内的赛璐id异步不起作用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。