Tk with Thread

S

Slickuser

I am currently using perl, v5.8.8 built for MSWin32-x86-multi-thread.

I have a Button on my GUI, when I pressed the button. It will parse
some file.
The parsing will run but my GUI will freeze. Once it's done parsing, I
can control my GUI again.

Is there a way to use Thread so my parsing is running and I can still
use my GUI?

I was looking at http://visitorflow.com/perl/lib/Thread.html

But it doesn't work for me. I also try 'threads' as well.

Any help?
 
B

Ben Morrow

Quoth Slickuser said:
I am currently using perl, v5.8.8 built for MSWin32-x86-multi-thread.

I have a Button on my GUI, when I pressed the button. It will parse
some file.
The parsing will run but my GUI will freeze. Once it's done parsing, I
can control my GUI again.

A straightforward way around this is to call $mainwindow->update
periodically during the processing. This can, however, be a little
tricky to arrange, depending on what the parsing consists of.
Is there a way to use Thread so my parsing is running and I can still
use my GUI?

Don't use Thread. It was part of the old 5005threads model that came
with 5.5; in 5.8 it is just a pass-through for threads.

It's best to read the documentation that comes with your version of
perl. That page appears to belong with 5.6.0: a lot has changed since
then, particularly wrt threads.
But it doesn't work for me. I also try 'threads' as well.

'Doesn't work' is not a helpful problem description. Please reduce your
program to a minimal example (preferably just a Tk window with a single
button, and a sub that calls something like 'sleep 500' to simulate the
parsing) and post it. Also describe what it is doing that you don't
expect.

Tk will work in multithreaded programs, but be sure to only access the
Tk objects from one thread. Tk itself isn't threadsafe.

Ben
 
Z

zentara

I am currently using perl, v5.8.8 built for MSWin32-x86-multi-thread.

I have a Button on my GUI, when I pressed the button. It will parse
some file.
The parsing will run but my GUI will freeze. Once it's done parsing, I
can control my GUI again.

Is there a way to use Thread so my parsing is running and I can still
use my GUI?

I was looking at http://visitorflow.com/perl/lib/Thread.html

But it doesn't work for me. I also try 'threads' as well.

Any help?


Here is a general purpose example. It creates threads before any
Tk is called, to be thread-safe. It creates a pool of 3 reusable
worker-threads, but you can cut down the complexity by using
just onw thread.

http://perlmonks.org?node_id=401819


You can also try the Tk::ExecuteCommand module.

#!/usr/bin/perl -w
use Tk;
use Tk::ExecuteCommand;
use Tk::widgets qw/LabEntry/;
use strict;

my $mw = MainWindow->new;

my $ec = $mw->ExecuteCommand(
-command => '',
-entryWidth => 50,
-height => 10,
-label => '',
-text => 'Execute',
)->pack;
$ec->configure(-command => 'date; sleep 10; date');


my $button = $mw->Button(-text =>'Do_it',
-background =>'hotpink',
-command => sub{ $ec->execute_command },
)->pack;

MainLoop;
__END__
 
S

Slickuser

So I should used threads and not Thread?

Also, I look at fork. Will this help me?

Thanks.
 
J

Joost Diepenmaat

Slickuser said:
So I should used threads and not Thread?

Yes. And make sure you've got a recent version of perl.
Also, I look at fork. Will this help me?

Maybe. You could also check out Tk::fileevent, perlopentut, and
IO::AIO on CPAN.
 
S

Slickuser

Here is a sample code:

use strict;
use warnings;
use Tk;
use threads;

my $mainWindow = MainWindow->new;
my $textBox = $mainWindow->Scrolled("Text", -width=>80, -height=>7, -
scrollbars=>"ose", -wrap=>"word")->pack();

$mainWindow->Button(-foreground=>"blue", -text=>"Click", -command=>
\&excecute)->pack();

MainLoop;

sub excecute
{
my $thr = threads->new(\&click);
$thr->join;
$thr->detach;
}

sub click
{

open(FILE,"C:/file.txt") or die "can't open\n";
while(<FILE>)
{
my $line = $_;

$textBox->insert('end', "$line\n");
$textBox->see('end');
$textBox->update;
}
return;
}


I got the following error:
Tk::Error: Can't call method "WidgetMethod" on an undefined value at
C:/Perl/sit
e/lib/Tk.pm line 252, <FILE> line 5568.
[set,{}]
(vertical scrolling command executed by text)
Tk::Error: Can't call method "WidgetMethod" on an undefined value at
C:/Perl/sit
e/lib/Tk.pm line 252, <FILE> line 5807.
[set,{}]
(vertical scrolling command executed by text)
Terminating on signal SIGINT(2)
 
J

Joost Diepenmaat

Slickuser said:
Here is a sample code:

use strict;
use warnings;
use Tk;
use threads;

my $mainWindow = MainWindow->new;
my $textBox = $mainWindow->Scrolled("Text", -width=>80, -height=>7, -
scrollbars=>"ose", -wrap=>"word")->pack();

$mainWindow->Button(-foreground=>"blue", -text=>"Click", -command=>
\&excecute)->pack();

MainLoop;

sub excecute
{
my $thr = threads->new(\&click);
$thr->join;
$thr->detach;
}

sub click
{

open(FILE,"C:/file.txt") or die "can't open\n";
while(<FILE>)
{
my $line = $_;

$textBox->insert('end', "$line\n");
$textBox->see('end');
$textBox->update;
}
return;
}

You shouldn't expect to be able to close over or otherwise refer to
objects in multiple threads, unless the docs for those objects
explictely say you can.

IOW: perl threads do not work like C/Java type low-level threads, and
mostly you want to minimize the communication between them.
 
B

Ben Morrow

[please quote properly]

Quoth Slickuser said:
So I should used threads and not Thread?
Yes.

Also, I look at fork. Will this help me?

Since you are on Win32, no. Win32 doesn't provide fork, and perl
emulates it using threads. If you aren't trying to write code which is
portable to Unix, it's probably better to use threads directly.

Ben
 
S

Slickuser

Here is the update code with the same error.

I would like to be able to move my Tk window when a button is press.
Currently, it's freeze until it's done parsing.

use strict;
use warnings;
use Tk;
use threads;

my $mainWindow = MainWindow->new;
my $textBox = $mainWindow->Scrolled("Text", -width=>80, -height=>7, -
scrollbars=>"ose", -wrap=>"word")->pack();

$mainWindow->Button(-foreground=>"blue", -text=>"Click", -command=>
\&excecute)->pack();

MainLoop;

sub excecute
{
my $thr = threads->new(\&click);
$thr->join;
#$thr->detach;
}

sub click
{
my @data;

open(FILE,"C:/file.txt") or die "can't open\n";
while(<FILE>)
{
my $line = $_;
push(@data,$line);
}
close(FILE);

$textBox->insert('end', "@data\n");
$textBox->see('end');
$textBox->update;

return;
}

Here is a sample code:

use strict;
use warnings;
use Tk;
use threads;

my $mainWindow = MainWindow->new;
my $textBox = $mainWindow->Scrolled("Text", -width=>80, -height=>7, -
scrollbars=>"ose", -wrap=>"word")->pack();

$mainWindow->Button(-foreground=>"blue", -text=>"Click", -command=>
\&excecute)->pack();

MainLoop;

sub excecute
{
my $thr = threads->new(\&click);
$thr->join;
$thr->detach;

}

sub click
{

open(FILE,"C:/file.txt") or die "can't open\n";
while(<FILE>)
{
my $line = $_;

$textBox->insert('end', "$line\n");
$textBox->see('end');
$textBox->update;
}
return;

}

I got the following error:
Tk::Error: Can't call method "WidgetMethod" on an undefined value at
C:/Perl/sit
e/lib/Tk.pm line 252, <FILE> line 5568.
[set,{}]
(vertical scrolling command executed by text)
Tk::Error: Can't call method "WidgetMethod" on an undefined value at
C:/Perl/sit
e/lib/Tk.pm line 252, <FILE> line 5807.
[set,{}]
(vertical scrolling command executed by text)
Terminating on signal SIGINT(2)

Yes. And make sure you've got a recent version of perl.
Maybe. You could also check outTk::fileevent, perlopentut, and
IO::AIO on CPAN.
 
B

Ben Morrow

You shouldn't expect to be able to close over or otherwise refer to
objects in multiple threads, unless the docs for those objects
explictely say you can.

More importantly, in this case, you mustn't access Tk (at all) from more
than one thread, since it isn't threadsafe.

Ben
 
Z

zentara

Here is the update code with the same error.

I would like to be able to move my Tk window when a button is press.
Currently, it's freeze until it's done parsing.

I get all sorts of errors regarding thread corruption, since you
created your thread after Tk is invoked, and you try to access the
Tk text widget from the thread. Gtk2 will allow you to do that, but Tk
won't. Even Gtk2 needs some precautions.

This is a basic Tk thread script, to show you the ropes.
You can search groups.google.com for "perl Tk threads"
and find all of the many examples that have been posted previously.

#!/usr/bin/perl
use strict;
use warnings;
use Tk;
use threads;
use threads::shared;

my $go:shared = 0;
my $die:shared = 0;
my $count:shared = 0;

# make thread before any Tk is called,
# usually a sleeping thread
my $thr = threads->new(\&new_thread);

my $mainWindow = MainWindow->new;
my $textBox = $mainWindow->Scrolled("Text", -width=>80, -height=>7,
-scrollbars=>"ose", -wrap=>"word")->pack();

$mainWindow->Button(-foreground=>"blue", -text=>"Click",
-command=>\&excecute)->pack();

$mainWindow->Button(-foreground=>"red", -text=>"Stop",
-command=>sub{ $go=0 })->pack();

$mainWindow->Button(-foreground=>"black", -text=>"exit",
-command=>sub{ $die=1;
$thr->join;
exit;
})->pack();

# you must actively read the shared variables with a timer
# filehandles can be shared thru the fileno,
# search groups.google for examples
my $repeater = $mainWindow->repeat(1000,sub{
if($go){
$textBox->insert('end', "$count\n");
$textBox->see('end');
$textBox->update;
}
});


MainLoop;

sub new_thread{

while(1){
if($die){return} #thread can only be joined after it returns
if( $go == 1){
if($die){return}

$count++;

}else{ select undef,undef,undef,.1} #sleep awhile
}
}

sub excecute { $go = 1 }
__END__



Those are the basics, but search groups.google.com, because
we have answered these questions many times before, with code examples.

zentara
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,209
Messages
2,571,088
Members
47,686
Latest member
scamivo

Latest Threads

Top