2

I have a WCF library exposing some useful information and I query them from powershell with New-WebServiceProxy cmdlet

$link = "http://localhost/Rlib/Rlib.Info.svc";
$service = New-WebServiceProxy -Uri $link;

Assume I have a function like GetLastData(), I usually invoke it this way

$service.GetLastData()

Now I've a very slow function that requires lot of time to complete (complex DB query that return a date), I see that an Async function is automatically generated and I can Invoke it using $service.GetLastDataAsync(). How does it work? Once I call the async method how can I check if data are available and recover them?

2
  • Does the $service object have a GetLastDataCompleted event as well? Commented May 13, 2015 at 13:04
  • Yes but it doesn't return any value Commented May 13, 2015 at 13:06

2 Answers 2

3

After you call the Async method, a corresponding event will be raised when the operation is finished (in your case GetLastDataCompleted).

You can use Register-ObjectEvent to "listen" for when this event is raised!

I used CDYNE's IP2Geo service for a quick test, but the idea is exactly the same with any other SOAP service:

$ServiceUri = 'http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl'
$Service = New-WebServiceProxy -Uri $ServiceUri

# Make sure the environment is clean
Remove-Variable -Scope Global -Name IPResult -Force | Out-Null
Unregister-Event -SourceIdentifier "IPResolved"

# Register an event subscription
Register-ObjectEvent -InputObject $Service -EventName ResolveIPCompleted -SourceIdentifier "IPResolved" -Action { $Global:IPResult = $args[1] } | Out-Null

# Initialize the operation with Async
$Service.ResolveIPAsync('8.8.8.8','')

# Do other stuff in the background here

# Wait for the variable to get populated
while(-not(Get-Variable -Scope Global -Name IPResult -ErrorAction SilentlyContinue)){
    Start-Sleep -Seconds 1
}

# Let's see what we got!
if($Global:IPResult.Error -eq $null){
    Write-Host "Success!"

    # The Result property holds the result from the operation
    $Global:IPResult.Result

} else {
    Write-Host "Failed!"
}
Sign up to request clarification or add additional context in comments.

1 Comment

It would be far easier just to poll the Task.IsCompleted property (from ResolveIPAsync)
2

How does it work?

GetLastDataAsync returns Task<something>, which can be used to track the process of an out-going operation. It can get quite complicated. You probably don't need to use async version, unless you have good reason to? You can use powershell jobs for synchronous version, and just poll how the job is doing.

Once I call the async method how can I check if data are available and recover them?

If you would like to wait for result, you could do GetLastDataAsync(..).Result, but this would be useless, as you can already use the synchronous one.

There is no easy way in my opinion to consume Task correctly. The closest I found was to use some kind of custom DLL, in this manner:

    C:\PS> $path = "$home\Pictures\foo.png"
    C:\PS> $asyncOp = [Windows.Storage.StorageFile]::GetFileFromPathAsync($path)
    C:\PS> Add-Type -Path ~\PoshWinRT.dll
    C:\PS> $typeName = 'PoshWinRT.AsyncOperationWrapper[Windows.Storage.StorageFile]'
    C:\PS> $wrapper = new-object $typeName -Arg $asyncOp
    C:\PS> $file = $wrapper.AwaitResult()
    C:\PS> $file

The theory behind wrapper is that it's using Task.Wait behind the scenes, which kind of beats the whole purpose of async. As it's still blocking the main thread.

TLDR; stick with synchronized version & scheduled jobs if you need.

https://rkeithhill.wordpress.com/2013/09/30/calling-winrt-async-methods-from-windows-powershell/

1 Comment

Thank you for the complete explanation. I think using New-Job on the synchronous method is a much more viable solution for my situation

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.