in reply to Annoying threads share problem!

Thread::Queue::Any could be the solution, IF I had some bright idea to use it! I mean, the updateSearch would add to the queue, but how to set up a listener in the "Tk" part? This would need a thread, but then Im back to square one again... seems impossible!

Replies are listed 'Best First'.
Re^2: Annoying threads share problem!
by zentara (Cardinal) on Oct 09, 2005 at 13:33 UTC
    Hi, I have played with Tk and threads quite abit, and although I don't really understand all of the underlying magic, this is what I have found.

    When mixing threads and Tk code, you must create your threads before you call any Tk statements. In my threaded Tk apps, I first create the number of threads I want, put them to sleep, and control them thru shared scalars. Tk is not thread-safe, and if you try to setup some Tk code, then create a thread, it will fail with odd errors. Also, you shouldn't try to run a second Tk event loop in a thread, unless it's the only loop, i.e. no event loop in main. So you are left with a basic template, of 1 Tk-event-loop in main, and a bunch of worker threads( which are non-Tk ), which communicate with main thry shared scalars and shared arrays. This type of program style runs well.

    Now say you do get the above program setup to run. There is another problem. Tk's useful technique of being able to specify a reference in a -textvariable option, which automatically reflects the change in the reference's value, will NOT work across threads. So you when you wake up a thread, and tell it to do something, you will have to actively read the shared scalars(arrays) in main. This can be done with a timer set very fast, like

    my $timer = $mw->repeat(10,sub{ $x = $shared{'x'}; $y = $shared{'y'}; $mw->update; });
    It can all be done with careful planning.

    I'm not really a human, but I play one on earth. flash japh
      I forgot to mention this, but the searchUpdate thread is supposed to update data in question when user types stuff in the entry... So, I wanted to avoid to do a $mw->repeat(xx...) to update when not neccessary, thus somehow make the searchUpdate thread update! and not the Tk one... hope you see the problem I have becasuse I can't make the searchUpdate update/change the Tk widget when it needs too...
        It sounds to me like you have to clarify and rethink your design. If you want to update something, when someone types something into the entrybox. Here is some code which does what your first example attempts to do.

        P.S. Use code blocks around your code examples.

        #!/usr/bin/perl use warnings; use strict; use Tk; use Tk::MatchEntry; use threads; use threads::shared; my %shash; my %hash; my @choices; share $shash{'go'}; share $shash{'die'}; share @choices; $shash{'go'} = 0; $shash{'die'} = 0; @choices = ( "01234", "345345", "64364" ); $hash{'thread'} = threads->new(\&work); my $mw = MainWindow->new( -title => "MatchEntry Test" ); #print Dumper(@choices); my $full_PathMatchEntry = $mw->MatchEntry( -width => 10, -choices => \@choices, -autopopup => 0, -complete => 1, -ignorecase => 1, -maxheight => 15, -background => "#FFFFFF" )->pack( -fill => 'x', -expand => 1, -side => 'left' ); $full_PathMatchEntry->focus; $full_PathMatchEntry->bind( '<KeyPress>', [ sub { shift; my $w = shift; $w->show_listbox(); }, $full_PathMatchEntry ] ); $mw->Button(-text=>'Do_Thread', -command=> sub { $shash{'go'} = 1; $mw->after(1000); $full_PathMatchEntry->configure(-choices => \@choice +s); })->pack(); MainLoop; sub work{ $|++; while(1){ if($shash{'die'} == 1){ goto END }; if ( $shash{'go'} == 1 ){ push( @choices, "/dfgsdfgsdfgsfse/ertuy/" ); $shash{'go'} = 0; #turn off self before returning }else { sleep 1 } } END: }

        I'm not really a human, but I play one on earth. flash japh