4

In C# when I want to create a thread which calls a function I simply do this.

Thread t = new Thread(() => calledFunction());
t.Start();

My goal is to do the same thing in Powershell. Nothing fancy, its only purpose is the prevent the GUI from freezing up. But i just cant find a working solution.

At the moment, I'm just trying to make the runspace to do anything. If I put this inside a click event of a button nothing happens.

$Runspace = [runspacefactory]::CreateRunspace()
$PowerShell = [powershell]::Create()
$PowerShell.runspace = $Runspace
$Runspace.Open()

[void]$PowerShell.AddScript({

    $test = "test"
    Write-Host $test

})

$PowerShell.Invoke()

But if I put a messagebox in the scriptblock then that works fine. It's very confusing to me when some things works and some things doesn't.

If you had a task where you had to call a function that does some work and updates a GUI. How would you go about calling that function in its own thread so that the GUI won't freeze while it's working in Powershell? In C# I have the easy example I posted above or using a BackgroundWorker.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jomasdf
  • 258
  • 2
  • 13

1 Answers1

1

If I put this inside a click event of a button

$PowerShell.Invoke() executes synchronously, so it will by definition block until the script you've added completes, so it will freeze the GUI.

nothing happens.

Write-Host $test (in PSv5+) writes to the information stream (stream number 6), which is not directly returned by an .Invoke() call - only success output (stream number 1) is; see about_Redirection.

Additionally, even if there were success output, outputting to the success stream from an event handler will not surface in the console (terminal).


If you had a task where you had to call a function that does some work and updates a GUI. How would you go about calling that function in its own thread so that the GUI won't freeze while it's working in Powershell?

See the following WPF-based answer, which can be adapted to WinForms with relatively little effort.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thank you the info! I found a working solution using a synchronized hashtable. However, some other quirk prevents me from calling functions stored in another file i have created. I guess I have to somehow import the file to the codeblock doing the work just like with the hashtable. Any Ideas? – Jomasdf Mar 01 '21 at 17:29
  • @Jomasdf, note that the linked WPF-based answer uses a thread-job-based approach with a single loop on the main thread (a `while` loop that essentially acts like a message loop after showing the GUI _non-modally_), which obviates the need for cross-thread synchronization in user code, which I think ultimately makes for simpler and more PowerShell-idiomatic code. As for your follow-up question: I encourage you to ask a _new_ question post, where you can supply enough details for others to understand the problem and help. Feel free to comment here to let me know once you have done so. – mklement0 Mar 01 '21 at 17:46
  • 1
    Thank you. I have posted a new question: https://stackoverflow.com/questions/66430360/call-function-from-module-inside-a-runspace – Jomasdf Mar 01 '21 at 22:07