多线程 – PowerShell:DownloadFileAsync的Runspace问题

前端之家收集整理的这篇文章主要介绍了多线程 – PowerShell:DownloadFileAsync的Runspace问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要在Power Shell 2.0中使用WebClient下载文件,我想显示下载进度,所以我这样做:
$activity = "Downloading"

$client = New-Object System.Net.WebClient
$urlAsUri = New-Object System.Uri($url)

$event = New-Object System.Threading.ManualResetEvent($false)

$downloadProgress = [System.Net.DownloadProgressChangedEventHandler] {
    $progress = [int]((100.0 * $_.BytesReceived) / $_.TotalBytesToReceive)
    Write-Progress -Activity $activity -Status "${progress}% done" -PercentComplete $progress
}

$downloadComplete = [System.ComponentModel.AsyncCompletedEventHandler] {
    Write-Progress -Activity $activity -Completed
    $event.Set()
}

$client.add_DownloadFileCompleted($downloadComplete) 
$client.add_DownloadProgressChanged($downloadProgress)

Write-Progress -Activity $activity -Status "0% done" -PercentComplete 0
$client.DownloadFileAsync($urlAsUri,$file)    

$event.WaitOne()

我收到一个错误没有可用Runspace在此线程中运行脚本.对于$downloadProgress处理程序中的代码,这是逻辑的.但是,如何为(可能)属于ThreadPool的线程提供Runspace?

更新:
请注意,这个问题的答案都值得阅读,如果可以的话我也会接受.

解决方法

谢谢stej点头.

Andrey,powershell有自己的线程池,每个服务线程保持一个线程指针到一个运行空间(System.Management.Automation.Runspaces.Runspace.DefaultRunspace静态成员暴露了这一点 – 并且在你的回调中将是一个空参考)最终这意味着使用自己的线程池(由.NET为异步方法提供的)很难(特别是在脚本中)来执行脚本块.

PowerShell 2.0

无论如何,没有必要玩这个,因为powershell v2完全支持事件发生:

$client = New-Object System.Net.WebClient
$url = [uri]"http://download.microsoft.com/download/6/2/F/" +
    "62F70029-A592-4158-BB51-E102812CBD4F/IE9-Windows7-x64-enu.exe"

try {

   Register-ObjectEvent $client DownloadProgressChanged -action {     

        Write-Progress -Activity "Downloading" -Status `
            ("{0} of {1}" -f $eventargs.BytesReceived,$eventargs.TotalBytesToReceive) `
            -PercentComplete $eventargs.ProgressPercentage    
    }

    Register-ObjectEvent $client DownloadFileCompleted -SourceIdentifier Finished

    $file = "c:\temp\ie9-beta.exe"
    $client.DownloadFileAsync($url,$file)

    # optionally wait,but you can break out and it will still write progress
    Wait-Event -SourceIdentifier Finished

} finally { 
    $client.dispose()
}

PowerShell v1.0

如果你坚持v1(这不是专门为你提到v2中的问题),你可以使用我的powershell 1.0事件管理单元在http://pseventing.codeplex.com/

异步回调

.NET中另一个棘手的区域是异步回调.没有什么直接在v1或v2的powerhell可以帮助你在这里,但你可以转换一个异步回调到一个简单的管道事件,然后处理该事件使用常规事件.我在http://poshcode.org/1382发布了一个脚本(New-ScriptBlockCallback)

希望这可以帮助,

-Oisin

猜你在找的Java相关文章