[fxruby-users] FXText update within threads

watobo watobo at siberas.de
Wed Feb 15 02:27:50 EST 2012


Hi fxruby-users,

I want to set the text (setText/appendText) of an FXText widget out of a
thread. As soon as the scroll bar appears in the widget the gui is not
responsive anymore. This behaviour only occurs under windows (Win7-64). Under
Linux it just works fine. 

Using FXDataTarget is not possible because it produces a big delay on
updating the widget. Additionally, if I use an FXDataTarget it seems that all my other message handlers disapear.

Here's the sample code which triggers the behaviour:

-------------8<--------------------

 #!/usr/bin/env ruby
require 'rubygems'
require 'fox16'

include Fox

class MyWorker

  @@pool_mutex = Mutex.new

  def subscribe(event, &callback)
    (@event_dispatcher_listeners[event] ||= []) << callback
  end

  def notify(event, *args)
    if @event_dispatcher_listeners[event]
      @@pool_mutex.synchronize do
        @event_dispatcher_listeners[event].each do |m|
          m.call(*args) if m.respond_to? :call
        end
      end
    end
  end

  def run
    progress = {}
    @total.times do |i|
      Thread.new(i) { |ii|
        msg = "#{@name}: #{ii}\n"
        puts msg + " - running ..."

        notify(:logger, msg)

        sleep 1
        puts msg + " - finished!"
      }
    end

  end

  def initialize(name, total = 100)
    @event_dispatcher_listeners = {}
    @total = total
    @name = name
  end
end

class MTTextTest < FXMainWindow
  @@textMutex = Mutex.new
  def initialize(app)
    # Call base class initializer first
    super(app, "Producer Test", :width => 800, :height => 600)
    frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)

    @textbox = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_AUTOSCROLL)
  
    showButton = FXButton.new(frame, "&Thread", :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)

    showButton.connect(SEL_COMMAND) do
     # @textbox.hide
      @tl = []
      10.times do |x|

      # print "\n* starting worker #{x}..."
        name = "w#{x}"
        worker = MyWorker.new(name, x*3)

        worker.subscribe(:logger) { |msg|
          begin

            @@textMutex.synchronize do
              @textbox.appendText( msg, false )
            end

          rescue => bang
            puts bang
            puts bang.backtrace
          end

        }
        worker.run
      end
    #  @textbox.appendText "ALL WORKERS STARTED !!!\n"
    # @tl.each do |t| t.join; end
    end

  end

  # Create and show the main window
  def create
    super                  # Create the windows
    show(PLACEMENT_SCREEN) # Make the main window appear
  end
end

if __FILE__ == $0
  # Construct the application object
  application = FXApp.new('Multi-Thread-Producer Test', 'FoxTest')

  # Construct the main window
  scribble = MTTextTest.new(application)

# Create the application
application.create

application.run
end

-------------8<--------------------

C:\Users\andy>ruby -e "require 'fox16'; puts \"Ruby: #{RUBY_VERSION}\nFox: #{Fox
.fxversion}\""
Ruby: 1.9.2
Fox: 1.6.44


Does anybody know what's wrong here?

Thanks,

Andy



More information about the fxruby-users mailing list