Using perl / tk streams to avoid window freeze / unresponsive
I am trying to use streams in my perl / tk application so that it doesn't hang when connecting to a remote mysql server.
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use DBD::mysql;
use Tk;
use threads;
use threads::shared;
our $type="mysql";
our $database="b_db";
our $host="mysite.com";
our $port="3306";
our $tablename="tc";
our $user="example";
our $pwd="********";
our $dsn="dbi:$type:$database:$host:$port";
my $thr=threads->create(\&con);
our $mw=new MainWindow;
$mw->Button(-text=>"Connect",-command=>\&con)->pack;
MainLoop;
sub con{
our $connect=DBI->connect($dsn,$user,$pwd)or die &mysql_Err;
print "done connecting\n" if $connect;
print "error\n" unless $connect;
}
$thr->detach;
but it still hangs when trying to connect. I tried using tk / fileevent:
#!/usr/bin/perl
use DBI;
use DBD::mysql;
use Tk;
our $type="mysql";
our $database="b_db";
our $host="mysite.com";
our $port="3306";
our $tablename="tc";
our $user="example";
our $pwd="********";
our $dsn="dbi:$type:$database:$host:$port";
our $mw=new MainWindow;
$mw->Button(-text=>"Connect",-command=>\&con)->pack;
sub con{
our $connect=DBI->connect($dsn,$user,$pwd)or die &mysql_Err;
$mw->fileevent($connect, "readable", \&contquery);
}
sub contquery{
$query="SELECT * FROM products ORDER BY id";
$queryhandle=$connect->prepare($query);
$queryhandle->execute;
$queryhandle->bind_columns(undef, \$product_id, \$price, \$product_name, \product_type);
while($queryhandle->fetch()){
print <<print;
Product Name: $product_name | Type: $product_type | Prict: $price
print
}
}
MainLoop;
but it still freezes. Can anyone advise me what could be causing this?
source to share
You are misunderstanding streams and sharing. our
does not split streams. To do this, you need to declare the variable as shared
.
Otherwise, from the moment you create
subthread, they have their own local copy of all variables. This will almost certainly be your problem - your thread connects to the database and then exits, completely independent of the main thread.
our
also doesn't do what you think it does - to exchange package variables (for example, nothing to do with streaming), which is irrelevant to your code. Attach my
.
You may be able to:
my $db_handle : shared;
And then in the stream:
$db_handle = DBI->connect($dsn, $user, $password);
But keep in mind that you cannot be sure when this will end, so it is very important to check before trying to use it on another thread.
source to share