Hello folks. I have a problem. I am writing a program using Tk. Now the Tk process is started with MainLoop which blocks. You obviously need another way of updating/writing/reading from/to the Tk objects. I am currently aware of a few ways of doing stuff like this:

1. Use the repeat/after toplevel Tk methods
2. Fork a new process
3. Use threads
4. IPC ??? (Never used pipes much...)
5. Manually update display fields using callbacks ( : ()
* NO THANKS, IT AINT EXACTLY DYNAMIC *
6. Use Threads::Shared; - But this is new to me and Im not sure you can share anything but simple scalars

Now, what I have tried to do is, be able to call Tk methods on Tk objects from the seperate worker_thread, ie; access the Tk objects from within the seperate worker thread, in this case (update_thread). I know you can share scalars, and perhaps array's, but but but what about a module ? I heard that Tk is unsafe with threads atm !?
use strict; use Tk; use Threads; my ($mw,$sent_recvd_listbox,$server_list_listbox); threads->new(\&update_thread)->detach; create_tk_window(); $mw->MainLoop; sub update_thread { print "update_thread called...\n"; while(1) { if(defined($server_list_listbox)) { # This never gets executed because the objects from # the tk module are out of scope ?????? $server_list_listbox->insert('end',"Some string data"); }else{ print "Couldn't insert any data cause this thread can't se +e the tk objects !?\n"; } sleep 1; } exit(); } sub create_tk_window { $mw=MainWindow->new ( -background=>'#dedede', -foreground=>'yellow', -title=>"FingerLick" ); $mw->geometry("802x618"); $mw->minsize(802,618); $mw->maxsize(802,618); $sent_recvd_listbox=$mw->Listbox ( -height=>1, -width=>60, -background=>'black', -foreground=>'yellow' )->pack(-side=>'bottom',-anchor=>'s',-pady=>2); $server_list_listbox=$mw->Scrolled ( "Listbox", -height=>20, -width=>60, -background=>'white', -foreground=>'black', -scrollbars=>'se', )->pack(); }
Running the script above ^^ for me on a windows 2000 machine with v5.8.3, the update_thread (obviously) will just continue printing "Couldn't insert any data cause this thread can't see the tk objects !?" until you interrupt it.

If you create the seperate thread (threads->new(\&update_thread)->detach;) after calling create_tk_window, it gives me the following error:
Free to wrong pool 1e46660 not 15d3f10 at C:/Perl/site/lib/Tk.pm line 228.
(oops, forgot to edit the logical drive out of the path ;)

I have also breifly attempted to share a globally scoped (ie; defined at the top of file) IO::Handle that I would write/read to/from both update_thread and the main process. Ie; instead of trying to call $server_list_listbox->insert('end',"blah"); from inside the while loop in the update_thread. But no results..lol.

I know I could use the Tk repeat method to timeout every n amount of time and run subroutines that collect data outputted from various seperate 'worker' threads, but it seems like a real pain in the side to do that. Im thinking I would have to use 'magic numbers' or predefined values, that both threads relate to specific global shared data. Ie; I would have
my $wt_display_code:shared; my $wt_data:shared; $mw->repeat(0.001,sub { display_worker_data() });
Then, in the display_worker_data() sub, check some shared scalar that relates to what data the worker_thread has to offer, and just as importantly, where it has to go (what Tk widget field).

Eg;
my $wt_display_code:shared; my $wt_data:shared; $mw->repeat(0.001,sub { display_worker_data() }); sub display_worker_data() { if($wt_display_code eq "SENT_RECVD") { my $data_for_display="Sent recvd: $wt_data"; $sent_recvd_listbox->insert('end',$data_for_display"); }elsif($wt_display_code eq "TIME_STATUS") { my $data_for_display="Time: $local_time"; $time_stats_listbox->insert('end',"$data_for_display"); }elsif(...) { ... }elsif(...) { ... } etc... }
BUT THAT IS A NIGHTMARE ^^ The number of possible value pairs are endless.

Is there a way to have the Tk module objects shared in both threads, you know, being able to access the Tk objects from a seperate process/thread ?

Maybe I should be using a simple pipe to communicate data between threads. Don't tell me to use fork. Because it gave me more greif than you can poke a stick at, thats why I am trying to use threads.

As much help as possible is most appreciated. Thanks folks - kabeldag (DU).

Janitored by Arunbear - added readmore tags, as per Monastery guidelines


In reply to Sharing Tk-module objects in threads by kabeldag

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.