[fxruby-users] FXText update within threads

Andreas Schmidt watobo at siberas.de
Thu Feb 16 02:18:31 EST 2012


Hi Ryan,

thanks a lot for this detailed explanation.
But I don't like the answer because it means a lot of work ;)

After all, I should have read this earlier:
http://www.fox-toolkit.net/faq#TOC-Is-FOX-thread-safe-Can-I-write-mult

-andy

 Am 15.02.2012 23:18, schrieb Melton, Ryan:
> 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.
> _______________________________________________
> fxruby-users mailing list
> fxruby-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/fxruby-users



More information about the fxruby-users mailing list