Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

PowerShell class instance methods cannot run concurrently #3651

Copy link
Copy link
@PaulHigin

Description

@PaulHigin
Issue body actions

This behavior changed between PowerShell versions 5.0 and 5.1. The change was to make PowerShell class method script blocks bound to the runspace in which they were created. If a class instance method is run from within a different runspace then it gets "marshaled" back to the original runspace (via engine events). The result is that if a single class instance is shared among multiple runspaces (e.g., a runspace pool) with the intention to execute instance methods concurrently, the methods run serially instead.

I don't know why this changed between 5.0 and 5.1 but it looks to be by design. @vors can you please comment?

Repro steps:

PS > (measure-command { .\RunspaceInstanceTest.ps1 }).TotalSeconds

RunspaceInstanceTest.ps1 file script:
class Writer
{
    static WriteLineS([string] $Msg)
    {
        for ($i=0; $i -lt 10; $i++)
        {
            [Console]::WriteLine("Static: Loop $i - $Msg")
            Start-Sleep -MilliSeconds 100
        }
    }

    WriteLineI([string] $msg)
    {
        for ($i=0; $i -lt 10; $i++)
        {
            [Console]::WriteLine("Instance: Loop $i - $Msg")
            Start-Sleep -MilliSeconds 100
        }
    }
}

$script = @'
    param ([object] $writerInstance, [string] $Title)

    class Writer
    {
        static WriteLineS([string] $Msg)
        {
            for ($i=0; $i -lt 10; $i++)
            {
                [Console]::WriteLine("Static: Loop $i - $Msg")
                Start-Sleep -MilliSeconds 100
            }
        }

        WriteLineI([string] $msg)
        {
            for ($i=0; $i -lt 10; $i++)
            {
                [Console]::WriteLine("Instance: Loop $i - $Msg")
                Start-Sleep -MilliSeconds 100
            }
        }
    }

    # Create new instance
    #$writerInstance = [Writer]::new()

    # Instance write
    $writerInstance.WriteLineI("$Title")

    # Static write
    #[Writer]::WriteLineS("$Title")
'@

$writer = [Writer]::new()

$rsp = [runspacefactory]::CreateRunspacePool(1, 10, $host)
$rsp.Open()

class Task
{
    [powershell] $powershell
    [System.IAsyncResult] $Async
}

$tasks = @()

1..5 | foreach {

    $task = [Task]::new()
    $tasks += $task

    $task.powershell = [powershell]::Create()
    $task.powershell.RunspacePool = $rsp
    $task.Async = $task.powershell.AddScript($script).AddArgument($writer).AddArgument("Task $_").BeginInvoke()
}

foreach ($task in $tasks)
{
    $task.powershell.EndInvoke($task.Async)
    $task.powershell.Dispose()
}

$rsp.Dispose()

Expected:
5 concurrently running 1 second loops (with sleep) should take about 1 second to run.

Actual Result:
It takes about 5 seconds to run indicating that the concurrent scripts are running serially.

Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugthe issue is more of a feature request than a bugResolution-FixedThe issue is fixed.The issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtime

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.