none
PowerShell and WPF Asynchronously displaying results from button click event RRS feed

  • Question

  • Can someone please help me with the following questions:

    I am experimenting with PowerShell and WPF

    I am using a thread safe synced hash table (as I learned about on an internet post)

    The following code works, but I have some questions/issues hence my post :)

    Basically if you save the code as a PowerShell script and execute it

    c:\script\myscript.ps1 

    you get two buttons one called 'Execute' the other "Stop" plus a Textbox for the output from the click event on the Execute Button

    As you can see there are 'two' separate actions under the click event.

    the first is

    $syncHash.txtBox1.Dispatcher.Invoke("Normal", [Action]{$syncHash.txtBox1.AppendText("`r`nPlease wait...")})

    which simple displays the text 'Please wait..."  in the textbox

    the second action is designed to take longer (for the purposes of this post) therefore the bigger range (currently 1..1000)  I give it the longer it will take.

    *** My Problem:

    I want the results of these two separate actions to be displayed independently in the textbox, in other words display the output of the first action, then move on to the second action.

    it kind of does this but, (and this is the actual issue) it 'waits' for 'all' the actions to complete under the 'click event' before display this results. e.g. you get nothing then once all actions are complete you get all the information displayed at the end. therefore the "please wait..." is useless as it is displayed at the end once every thing is finished.

    Any ideas please, thanks very much in advance.

    code below this line

    ----------------------------------------------------------------------------------------------------------------------------------------------

    #Sync'd hash table to work between runspaces
    $Global
    :syncHash = [hashtable]::Synchronized(@{})
    # Invoke STA Runspace (WPF works in single thread apartment)
    $threadSTA
    = [RunspaceFactory]::CreateRunspace()
    $threadSTA
    .ApartmentState = "STA"
    #$threadSTA.ThreadOptions = "ReuseThread"
    $threadSTA
    .Open()
    $threadSTA
    .SessionStateProxy.SetVariable("syncHash",$syncHash)
    # Load WPF assemblies to STA Runspace
    $psShell
    = {Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase}.GetPowerShell()
    $psShell
    .Runspace = $threadSTA
    $psShell
    .Invoke()
    $psShell
    .Commands.Clear()
    [void]$psShell.AddScript({

       
    ########################################
       
    # WPF XAML Description
       
    ########################################

        $String
    = @'
        <Window x:Name="wdwMain"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                Title="MainWindow" Height="350" Width="525">
            <Grid Margin="0,0,-72,-9">
                <Canvas HorizontalAlignment="Left" Height="289" Margin="10,10,0,0" VerticalAlignment="Top" Width="475">
                    <Button x:Name="btnExecute" Content="Execute" Canvas.Left="10" Canvas.Top="10" Width="75" Cursor="Hand" ToolTip="Execute Button"/>
                    <TextBox x:Name="txtBox1" Height="269" Canvas.Left="112" TextWrapping="Wrap" Text="Some Text" Canvas.Top="10" Width="344" />
                    <Button x:Name="btnStop" Content="Stop" Canvas.Left="10" Canvas.Top="37" Width="75"/>
                </Canvas>
            </Grid>
        </Window>
        '
    @
       
    [xml]$XAML = ($String -replace "x:")
       
    ########################################
       
    # Load Xaml
       
    ########################################
        $reader
    = (New-Object System.Xml.XmlNodeReader $xaml)
       
    try { $Synchash.Form = [System.Windows.Markup.XamlReader]::Load($reader)}
       
    catch{exit}

        $XAML
    .SelectNodes("//*[@Name]")| % {$syncHash."$($_.Name)" = $syncHash.Form.FindName("$($_.Name)")}

        $syncHash
    .btnStop.Add_Click({
            $syncHash
    .btnStop.Dispatcher.Invoke("Send", [Action] {break})
       
    })

        $syncHash
    .btnExecute.Add_Click({
            $syncHash
    .txtBox1.Dispatcher.Invoke("Normal", [Action]{$syncHash.txtBox1.AppendText("`r`nPlease wait...")})

           
    function UpDateTextBox {param([parameter(ValueFromPipeLine=$true)]$Message)
                $syncHash
    .txtBox1.Dispatcher.Invoke("Normal", [Action]{
                $syncHash
    .txtBox1.AppendText("`r`n$Message")
               
    })
           
    }
            $Array
    = 1..1000

           
    foreach ($item in $Array) {
               
    UpDateTextBox $item
           
    } 
       
    })

        $SyncHash
    .Form.ShowDialog() | out-null

       
    ################# End Dialog ########################

    }).BeginInvoke()

    Tuesday, July 29, 2014 5:08 AM

Answers

All replies