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?

+3


source to share


2 answers


See PerlMonks : Tk is not thread safe.



  • Create a thread before creating any Tk widgets.
  • Don't touch Tk objects from stream, use shared variables for communication.
+3


source


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.

+2


source







All Articles