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.

3
  • Can you instead Start-Job and then asynchronously wait for completion? Commented Feb 28, 2021 at 0:12
  • You need to add a Synchronized hashtable Commented Feb 28, 2021 at 1:07
  • 2
    Take a look at the following: learn-powershell.net/2013/04/19/… Commented Feb 28, 2021 at 1:08

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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, 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.
Thank you. I have posted a new question: stackoverflow.com/questions/66430360/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.