---
title: "Real-World Async Functions in PowerShell"
description: "Improve script performance with asynchronous functions in PowerShell. Learn through real-world examples."
canonical: "https://adamtheautomator.com/powershell-async/"
---

# Real-World Async Functions in PowerShell

> Improve script performance with asynchronous functions in PowerShell. Learn through real-world examples.

Source: https://adamtheautomator.com/powershell-async/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Real-World Async Functions in PowerShell](https://adamtheautomator.com/wp-content/uploads/2019/06/5d238ae5c824b514689ea56b.jpg)

# Real-World Async Functions in PowerShell

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)28 June 20192 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)

Table of Contents

*   [Build the Code as Normal](#build-the-code-as-normal)
*   [Build the Function Parameters](#build-the-function-parameters)
*   [Implement PowerShell Async Job Support](#implement-job-support-with-scriptblocks)
*   [Provide Support for Synchronous Operation](#provide-support-for-synchronous-operation)

The most frequent kind of PowerShell function is a function that executes code and, when finished, returns control back to the console. This is called synchronous code or a PowerShell async function. This means further code execution will not continue until that function’s execution is complete.

Related:[PowerShell Multithreading: A Deep Dive](https://adamtheautomator.com/powershell-multithreading/)

There are those times when the code inside of your function may take a while, and you don’t feel like waiting around until it’s done. In this case, you need to build functions that immediately return control but continue running a thread in the background.

I use asynchronous functions to clean up Azure VMs, for example. The process takes up to 5 minutes because it must bring down the VM, remove the VM and clean up all of the attached disks. It’s much easier to simply have my custom function return a background job object and monitor that when I have time.

PowerShell async functions can be written in a few different ways; [workflows](https://docs.microsoft.com/en-us/system-center/sma/overview-powershell-workflows), parallel runspaces, and [jobs](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_jobs) to name a few. Each has its advantages and disadvantages. However, I typically use jobs to run asynchronous code. I do this because they’re typically easy to manage and are intuitive to me.

Let’s say I have a need for a function that removes an Azure virtual machine. Within this function, I need to remove the VM, which takes a few minutes and does some other cleanup tasks.

I want to build a function that allows me to return a background job object but also give the user the option to wait for the function if they need to.

Always give the option to wait just in case there might be a time when you develop a script that might require that functionality.

## Build the Code as Normal

To remove a VM in Azure is simple with the Azure PowerShell cmdlet `Remove-AzVM` which requires a few parameters; `Name` and `ResourceGroupName`.

This would remove an Azure VM of mine: `Remove-AzVM -Name MYVM -ResourceGroupName MYRG`.

Related:[How to Delete an Azure VM and Cleanup with PowerShell](https://adamtheautomator.com/azure-vm-delete/)

Done. I now have the “typical” code to remove an Azure VM.

## Build the Function Parameters

To build a function around this to run in the background, I’ll need to build it to support the parameters that `Remove-AzVm` needs so `Name` and `ResourceGroupName`.

```powershell
function Remove-MyAzureRmVM
{
    param (
        [Parameter(Mandatory)]
        [string]$Name,

        [Parameter(Mandatory)]
        [string]$ResourceGroupName
    )
    Remove-AzureRmVm -Name $Name -ResourceGroupName $ResourceGroupName
}
```

I now have a simple proxy function that passes two parameters to the `Remove-AzVm` cmdlet. This works, but it’s not much good because it’s running synchronously. We need to make it into a PowerShell async function and implement PowerShell job support but also give the user the option to run it synchronously if they want.

## Implement PowerShell Async Job Support

To do this, we’ll need to put our code into a scriptblock. This allows us to not only pass it to `Start-Job` but also just to execute it if the user wants to wait for the operation to complete. Since `Remove-AzVm` requires some parameters from the function, we must also add these parameters to the scriptblock as well.

```powershell
$scriptBlock = {
    param ($Name,$ResourceGroupName)
    Remove-AzureRmVm -Name $Name -ResourceGroupName $ResourceGroupName
    ## Other stuff here
}
```

Once the code is in the scriptblock, you can then simply pass it to `Start-Job`, and you’re off to the races! Just be sure to pass in the arguments as necessary.

```powershell
Start-Job -ScriptBlock $scriptBlock -ArgumentList @($VMName,$ResourceGroupName)
```

## Provide Support for Synchronous Operation

Since the code is in a scriptblock, we can now also execute this on its own by using the ampersand and passing in the parameters again.

```powershell
& $scriptBlock -VMName $VMName -ResourceGroupName $ResourceGroupName
```

So we’ve now got both ways to execute the code. All we need to do now is provide a way for the function to specify which one we want.

By default, I want the code to be executed in a background job, but I want the option to execute it synchronously if need be. A great way to implement this functionality is to use the `Wait` parameter as a switch type. This allows me to quickly “turn on” synchronous behavior if I need to.

```powershell
Remove-MyAzVM -VMName MYVM -ResourceGroupName MYRG -Wait
```

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-async%2F&text=Real-World%20Async%20Functions%20in%20PowerShell)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-async%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-async%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2025/10/image_2025-10-24_095322075.png)

### [Migrating from PowerShell 6 to 7.5: Breaking Changes/New Features](/migrating-powershell-6-to-7-5/)

Migrate from PowerShell Core 6 to 7.5: breaking changes, features, and testing tips.

![](https://adamtheautomator.com/wp-content/uploads/2025/06/featured-image-6.png)

### [How to Add Timeouts to Pester Tests with PowerShell Runspaces](/pester-test-timeout-runspaces/)

Prevent Pester tests from hanging indefinitely using PowerShell runspaces. Learn to handle variable scoping, module loading, TestDrive access, and stream capture challenges with timeout protection.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
