Ace128 has asked for the wisdom of the Perl Monks concerning the following question:

Alright Monks,

I have this "global" variable.
use threads::shared; my $richEdit : shared;
Now, in a sub I do:
sub something { $richEdit = new Win32::GUI::RichEdit ( $infoWindow, -width => 400, -height => 200, -name => "RichEdit", -text => $text, -tabstop => 1, #-disabled=> 1, -autovscroll => 1, -addstyle => WS_CHILD | WS_VISIBLE + | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL #| ES_READONLY | ES_WANTRETURN -addexstyle => WS_EX_CLIENTEDGE ); }
However, at this point of creating the variable I get the error:
"Invalid value for shared scalar at tests.pl line..."
I've tried different approaches, but I cant make this work. I got another variable (an array) which I share the same way, and that works fine. What to do?
(I wanna share this so I can add/delete text from this in other threads)

Thanks,
Ace

Replies are listed 'Best First'.
Re: Sharing Win32::GUI::RichEdit...
by BrowserUk (Patriarch) on Jul 06, 2005 at 06:26 UTC

    Try this. Pass the (unshared) richtext window object to the thread as a parameter and then use it. It works fine.

    This minimally modified version of the sample program starts a thread that sits in the background, periodically quering the text from the RichEdit Window and prints it to terminal. As you type into the window you will see what you type printed to the shell window from where you started the program.

    #! perl -slw use strict; use threads; use threads::shared; use Win32::GUI; sub thread { my( $Textbox ) = @_; while( 1 ) { sleep 3; print $Textbox->Text; } } my $Font = new Win32::GUI::Font( -name => "Courier New", -height => 16, ); my $Menu = Win32::GUI::MakeMenu( "&File" => "File", "> &Load" => "FileLoad", "> &Save" => "FileSave", ); my $Window = new Win32::GUI::Window( -name => "Window", -text => "Win32::GUI TEST - RichEdit", -width => 500, -height => 400, -left => 100, -top => 100, -font => $Font, -menu => $Menu, ); my( $text ); my $Textbox = $Window->AddRichEdit( -name => "Text", -text => $text, -left => 5, -top => 5, -width => $Window->ScaleWidth-10, -height => $Window->ScaleHeight-10, -style => WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL, -exstyle => WS_EX_CLIENTEDGE, ); threads->new( \&thread, $Textbox )->detach; $Window->Show(); Win32::GUI::Dialog(); sub Window_Resize { my ($width, $height) = ($Window->GetClientRect)[2..3]; $Textbox->Resize($width-10, $height-10); } sub FileSave_Click { $Textbox->Save("richedit.rtf"); } sub FileLoad_Click { $Textbox->Load("richedit.rtf"); } sub Window_Terminate { return -1; }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Alright! Thanks, however, seems like I missed something "important". The thread is actually the GUI part...
      my $GuiThread = threads->create("startSystray"); sub startSystray { $mw_win32 = new Win32::GUI::Window( -width => 0, -height => 0, -name => 'MainWindow'); $systray_menu = new Win32::GUI::Menu( "SystrayMenu Functions" => "SystrayMenu", "> Info" => "SystrayInfo", "> Exit" => "SystrayExit" ); new Win32::GUI::NotifyIcon($mw_win32, -name => "SysTray", -id => 1, -icon => $icon); my $call = Win32::GUI::Dialog(); } sub SystrayInfo_Click { # my $A = new Win32::GUI::AcceleratorTable( # #"Ctrl-X" => "Close", # "Shift-N" => "New", # #"Ctrl-Alt-Del" => "Reboot", # "Shift-A" => sub { print "Hello\n"; }, # ); $infoWindow = new Win32::GUI::Window ( $mw_win32, -width => 400, -height => 200, -left => 300, -top => 400, -name => "infoWindow", # -accel => \$A ); my $text = join "\n", @actionHistory; $richEdit = new Win32::GUI::RichEdit ( ... ); }
      That is, the GUI is a thread on its own. Not sure how to solve this, and in a good way. I can't really send the $richEdit to the _Click() function... Not that I know of anyway. (That's one of the reasons I have the richedit as global...) Thing is, the $richEdit is not defined for thread 1 (the noneGUI thread) for starters. Its only defined when user klicks in tray. So, I cant pass like that either it seems... Hmm...

      Edit: Maybe Im gonna create the GUI, and hide it. Only show when klicking in tray...
        If you download The GUI Loft, there is a demo program that uses threads and message queues between them for keeping the GUI active during lengthy operations (the FetchURL-threads demo). That way the GUI part can be kept in one single thread and all is good.

        Update: The trick is also to not create windows on the fly unless you really need to. Just create them on program startup, and Hide() and Show() them as appropriate.

        /J

Re: Sharing Win32::GUI::RichEdit...
by ikegami (Patriarch) on Jul 06, 2005 at 04:27 UTC

    Win32::GUI::RichEdit wraps a window handle, and I don't know how thread safe that is. It's probably not something you should do, even if you could.

    One way of handling this is to have your other threads send Windows messages to the main thread. Message handlers you'd add to the main thread would perform the real work.

Re: Sharing Win32::GUI::RichEdit...
by duff (Parson) on Jul 06, 2005 at 04:04 UTC

    I tend to shy away from threads and Win32 if at all possible but I seem to recall that it is a known limitation of the current threading implementation that you can not share blessed references. Perhaps that's the reason for your error.

    Why do you need threading anyway? Have you looked at POE?

        Not that I've heard of, but if the POE main event loop can call Win32::GUI::DoEvents frequently that would work.

        Not that it wouldn't block the GUI whenever something else does something time consuming, so I don't know how useful it would be as a general solution.

        /J