Skip to content

Task-based Asynchronous Pattern #6716

Closed

Description

I am wondering if PowerShell has or will have in the future native support for the Task-based Asynchronous pattern in C#.

It would be nice to have some sugar for async and await but also just being able to work with .NET apps that rely heavily on this pattern (such as Kestrel) without having to worry about managing runspaces would be very nice.

I did find SeeminglyScience has a couple of PowerShell classes for a start on sample implementation as well as some basic functions to support async and await for some ideas on what I'm looking for:
https://www.powershellgallery.com/packages/EditorServicesCommandSuite/0.4.0/Content/Classes%5CAsync.ps1

Activity

  1. BrucePay commented on Apr 24, 2018

    @BrucePay
    Collaborator

    The referenced code takes a subset of the PowerShell syntax and turns it into .NET delegates but it is essentially a different language (e.g. no commands) . PowerShell concurrency is fundamentally based on runspaces. I wrote an RFC for a task(ish) based model of concurrency a while back Native Support for Concurrent Programming in PowerShell but it hasn't gone anywhere. As far as await goes, I suspect doing the lift-and-split that C# does would be tricky in PowerShell (but I haven't looked at it a whole lot.) Now I do like Golang's model of concurrency with tasks and channels - maybe we should do that :-)

    Anyway, can you provide more specific scenarios/examples of what you'd like to do? Even if we can't do a fully general implementation, I sure there's something useful we can do.

  2. Tiberriver256 commented on Apr 24, 2018

    @Tiberriver256
    Author

    Sure thing! So we are in the middle of a rewrite of https://github.com/PowerShell/Polaris to a pure PowerShell implementation and are currently using HttpListener which works fine cross-platform for now but as HttpListener doesn't seem to be getting any development love lately we're looking at the new hotness Kestrel.

    We are currently working with HttpListener's event based asynchronous support and using Oisin Grehan (@oising)'s marvelous function New-ScriptBlockCallback to provide an AsyncCallback. I was hoping to find the same thing in Kestrel but it appears that they only support the task based asynchronous pattern which I can't see an easy way to convert to an event based pattern.

    The sample code that I would love to write and just have work is this sample: (simplified from this sample in C#)

    Import-Module .\lib\Microsoft.AspNetCore.dll
    Import-Module .\lib\Microsoft.AspNetCore.Diagnostics.dll
    Import-Module .\lib\Microsoft.AspNetCore.Hosting.dll
    Import-Module .\lib\Microsoft.AspNetCore.Server.Kestrel.dll
    
    class StartUp {
        [void] Configure([IApplicationBuilder]$App){
            [DeveloperExceptionPageExtensions]::UseDeveloperExceptionPage($App)
            [RunExtensions]::Run($App, async $context => {
                    param($context)
                    return ([Microsoft.AspNetCore.Http.HttpResponseWritingExtensions]::WriteAsync($Context.Response, "Hello World", [Threading.CancellationToken]::None))
          })
        }
    }
    
    
    #$Env:ASPNETCORE_ENVIRONMENT = "Development"
    
    $WebHostBuilder = $Null
    [IWebHostBuilder]$WebHostBuilder = [Microsoft.AspNetCore.WebHost]::CreateDefaultBuilder()
    $WebHostBuilder = [WebHostBuilderExtensions]::UseStartup($WebHostBuilder, [StartUp])
    $WebHostBuilder = [WebHostBuilderKestrelExtensions]::UseKestrel($WebHostBuilder)
    $WebHost = $WebHostBuilder.Build()
    
    $Result = $WebHost.StartAsync()

    This is my specific use-case at the moment but I think there are quite a few other .Net projects that rely heavily on the task based asynchronous pattern that are currently fairly complex to work with natively in PowerShell.

    Thanks for your thoughts!

  3. BrucePay commented on Apr 24, 2018

    @BrucePay
    Collaborator
  4. oising commented on Apr 27, 2018

    @oising
    Contributor

    So, back when I had more ideas than the focus to complete most of them, I wrote a threads/tasks prototype extension to my old PSEventing library that could handle tasks, apm (iasyncresult) and callbacks. It got annoying as I tried to deal with runspaces, and while I had solutions, it just seemed to unwieldy and inelegant so I just got bored with it. Anyway, you may have some luck if you grok System.Threading.Tasks.Task.FromAsync (APM to Task methods) and the non-public static class System.Threading.Tasks.TaskToApm which goes in the other direction: Task to APM.

  5. oising commented on Apr 27, 2018

    @oising
    Contributor

    Ok, so that works.

    find-module poke | install-module -scope currentuser
    ipmo poke
    $tasksToApm = peek -Name System.Threading.Tasks.TaskToApm
    $task = [System.Threading.Tasks.Task]::CompletedTask
    $cb = New-ScriptBlockCallback -Callback { write-host "completed!" }
    $ar = $tasksToApm.Begin($task, $cb, $null)
    completed!
    

    Obviously I'm not suggesting a dependency on my Poke module, but it's just to facilitate the proof of concept here :)

  6. SeeminglyScience commented on Apr 27, 2018

    @SeeminglyScience
    Contributor

    Bruce Payette (@BrucePay)

    The referenced code takes a subset of the PowerShell syntax and turns it into .NET delegates but it is essentially a different language (e.g. no commands) .

    I believe you're thinking of PSLambda :)

    The referenced code was an earlier attempt with a similar idea, but it just creates an lambda expression that invokes the script block against a RunspacePool.

  7. fMichaleczek commented on Apr 6, 2019

    @fMichaleczek
    Contributor

    I found this tweet today from David Fowl from AspNet Core Team :

    https://twitter.com/davidfowl/status/1004237863913906176

    Next, If you ever need to invoke a method on a type via reflection and that method could be async, we have a helper that we use everywhere in the http://ASP.NET Core code base that is highly optimized and flexible. The ObjectMethodExecutor

    https://github.com/aspnet/Extensions/blob/ff87989d893b000aac1bfef0157c92be1f04f714/shared/Microsoft.Extensions.ObjectMethodExecutor.Sources/ObjectMethodExecutor.cs

    Do you think this code could be implemented as keyword "await" in PowerShell ?

  8. chriskuech commented on Jul 6, 2019

    @chriskuech

    Would it be possible to implement await as a cmdlet instead of a keyword? The problem I see with JS's await is that it ruins chaining and would have similar impact to PowerShell pipelines. I think the semantics around Jobs circumvent this issue--perhaps we can use similar semantics for Tasks.

    1..10 | % {Invoke-WebRequest "https://mysite?i=$_" -Async} | Wait-Task | % {Invoke-Something $_}
  9. Bartolomeus-649 commented on Jul 26, 2019

    @Bartolomeus-649

    Also, when working with tasks and parallel stuff, a lot of functionality is implemented as extension methods, so easy, straight forward access to extension methods would be great in this context.

  10. oising commented on Sep 5, 2019

    @oising
    Contributor

    Couldn't a Task continuation be represented by a specialization of a ThreadJob?

  11. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  12. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  13. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  14. microsoft-github-policy-service commented on Nov 23, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

  15. alx9r commented on Nov 30, 2024

    @alx9r

    Couldn't a Task continuation be represented by a specialization of a ThreadJob?

    Oisin Grehan (@oising) For what it's worth, I tried exactly this and it works. I'm not yet sure how usable Task-based concurrency can be made in PowerShell, but it looks promising, at least. It's certainly working better than manually managing the dysfunctional preponderance of ThreadJobs and .Net Tasks that I so often end up with in PowerShell.

    My basic "JobTask" implementation spans at least hundreds if not thousands of lines of code by the time all of the .Net/PowerShell interop is complete, though. If there's still interest in this, I think I could contrive a toy version to post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions