[fxruby-users] FXText update within threads

Melton, Ryan rmelton at ball.com
Wed Feb 15 17:18:24 EST 2012


Most GUI frameworks (including FOX) are designed to the reactor pattern http://en.wikipedia.org/wiki/Reactor_pattern much like the EventMachine library (ie. one thread that services events) and are not thread safe.  What that means is that things may work sometimes, but not always if you touch the GUI outside of the main thread.  Due to Ruby 1.9 using native threads, problems jump out a lot faster when running 1.9, but they still existed in 1.8.  I've learned this the hard way with some very subtle and "spurious" failures in applications I have written.

Note that code that is not thread safe will work just fine across threads as long as a context switch does not occur while it is executing.  Calls that take a long time, like calls to FXText, are much more likely to have a context switch occur while they are executing.

If any of the example code touches the GUI from a Thread.new, then it is a BAD example.  May work sometimes, or even most of the time, but othertimes you will get a nice "spurious" crash. :)

Ryan

-----Original Message-----
From: fxruby-users-bounces at rubyforge.org [mailto:fxruby-users-bounces at rubyforge.org] On Behalf Of Andreas Schmidt
Sent: Wednesday, February 15, 2012 1:19 PM
To: fxruby-users at rubyforge.org
Subject: Re: [fxruby-users] FXText update within threads

Hi Ryan,

why not? Even in the groupbox.rb example a thread is used to update the
clock. I've often used threads to control widgets and it worked all the
time with Ruby 1.8. In Ruby 1.9 a lot of the thread managment changed,
you can use threads to control FXTables, FXLabel or FXProgressBar
without any problems. But I experienced this problem with FXText widget
and I don't understand where this problem lies. Is it a problem of
FXRuby or of the Fox-Toolkit?

thanks,
-andy


 Am 15.02.2012 16:53, schrieb Melton, Ryan:
> You're not allowed to interact with the GUI from threads.   You need to put any GUI function calls inside of a timeout handler so that they execute in the main thread.
>
> Ryan
>
> -----Original Message-----
> From: fxruby-users-bounces at rubyforge.org [mailto:fxruby-users-bounces at rubyforge.org] On Behalf Of watobo
> Sent: Wednesday, February 15, 2012 12:28 AM
> To: fxruby-users at rubyforge.org
> Subject: [fxruby-users] FXText update within threads
>
> 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
>
> _______________________________________________
> fxruby-users mailing list
> fxruby-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/fxruby-users
>
>
>
> This message and any enclosures are intended only for the addressee.  Please  
> notify the sender by email if you are not the intended recipient.  If you are  
> not the intended recipient, you may not use, copy, disclose, or distribute this  
> message or its contents or enclosures to any other person and any such actions  
> may be unlawful.  Ball reserves the right to monitor and review all messages  
> and enclosures sent to or from this email address.
> _______________________________________________
> fxruby-users mailing list
> fxruby-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/fxruby-users

_______________________________________________
fxruby-users mailing list
fxruby-users at rubyforge.org
http://rubyforge.org/mailman/listinfo/fxruby-users



This message and any enclosures are intended only for the addressee.  Please  
notify the sender by email if you are not the intended recipient.  If you are  
not the intended recipient, you may not use, copy, disclose, or distribute this  
message or its contents or enclosures to any other person and any such actions  
may be unlawful.  Ball reserves the right to monitor and review all messages  
and enclosures sent to or from this email address.


More information about the fxruby-users mailing list