Powershell New-WebServiceProxy异步方法

时间:2015-05-13 12:32:59

标签: c# wcf powershell asynchronous

我有一个WCF库,公开了一些有用的信息,我使用New-WebServiceProxy cmdlet从powershell查询它们

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

假设我有一个像GetLastData()这样的函数,我通常以这种方式调用它

$service.GetLastData()

现在我的功能非常慢,需要很多时间才能完成(返回日期的复杂数据库查询),我看到自动生成了异步函数,我可以使用$service.GetLastDataAsync()调用它。它是如何工作的?一旦我调用异步方法,我如何检查数据是否可用并恢复它们?

2 个答案:

答案 0 :(得分:2)

  

它是如何工作的?

GetLastDataAsync返回Task<something>,可用于跟踪外出操作的过程。它会变得非常复杂。除非你有充分的理由,否则你可能不需要使用异步版本?您可以将powershell作业用于同步版本,并仅轮询作业的工作方式。

  

一旦我调用异步方法,我该如何检查数据是否可用   恢复它们?

如果您想等待结果,可以GetLastDataAsync(..).Result,但这没用,因为您已经可以使用同步了。

在我看来,没有简单的方法可以正确使用Task。我发现最接近的是以这种方式使用某种自定义DLL:

    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

包装器背后的理论是它在幕后使用Task.Wait,这类似于async的全部目的。因为它仍在阻止主线程。

<强> TLDR;坚持同步版本&amp;如果需要,可以安排工作。

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

答案 1 :(得分:2)

调用Async方法后,操作完成时会引发相应的事件(在您的情况下为GetLastDataCompleted)。

您可以使用Register-ObjectEvent“监听”此事件何时被提升!

我使用CDYNE's IP2Geo service进行快速测试,但这个想法与任何其他SOAP服务完全相同:

$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!"
}