web-dev-qa-db-ja.com

PowerShellからの非同期C#メソッドを待つ

次のような静的メンバーアクセサーを使用して、PowerShellから静的非同期C#メソッドを呼び出します。

PowerShell

function CallMyStaticMethod([parameter(Mandatory=$true)][string]$myParam)
{
    ...
    [MyNamespace.MyClass]::MyStaticMethod($myParam)
    ...
}

C#

public static async Task MyStaticMethod(string myParam)
{
    ...
    await ...
    ...
}

C#メソッドは非同期であるため、PowerShellから何らかの "await"呼び出しを行わなくても、C#メソッドは正しく実行されますか?

9
BlueTriangles

そのままでも問題なく動作しますが、完了するまで待つ場合は、これを使用できます。

$null = [MyNamespace.MyClass]::MyStaticMethod($myParam).GetAwaiter().GetResult()

これは、代わりに$task.Resultのようなものを使用した場合にスローされるAggregateExceptionのラップを解除します。

ただし、それが完了するまでブロックされるため、CTRL + Cがパイプラインを適切に停止できなくなります。このようにパイプラインの停止に従っている間、それが完了するのを待つことができます

 $task = [MyNamespace.MyClass]::MyStaticMethod($myParam)
 while (-not $task.AsyncWaitHandle.WaitOne(200)) { }
 $null = $task.GetAwaiter().GetResult()

Asyncメソッドが実際に何かを返す場合は、$null =を削除します

16

Patrick Meineckeの答えを借りて、タスク(またはタスクのリスト)を解決するパイプライン可能な関数を作成することができます。

function Await-Task {
    param (
        [Parameter(ValueFromPipeline=$true, Mandatory=$true)]
        $task
    )

    process {
        while (-not $task.AsyncWaitHandle.WaitOne(200)) { }
        $task.GetAwaiter().GetResult()
    }
}

使用法:

$results = Get-SomeTasks $paramA $paramB | Await-Task
5
JLRishe