PowerShell:DownloadFileAsync的运行空间问题 [英] PowerShell: Runspace problem with DownloadFileAsync

查看:104
本文介绍了PowerShell:DownloadFileAsync的运行空间问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在PowerShell 2.0中使用WebClient下载文件,并且我想显示下载进度,所以我这样做是这样的:

I needed to download file using WebClient in PowerShell 2.0, and I wanted to show download progress, so I did it this way:

$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()

我在$downloadProgress处理程序中收到代码错误There is no Runspace available to run scripts in this thread.,这是合乎逻辑的.但是,如何为(可能)属于ThreadPool的线程提供Runspace?

I am getting a error There is no Runspace available to run scripts in this thread. for the code in $downloadProgress handler, which is logical. However, how do I provide a Runspace for the thread that (probably) belongs to the ThreadPool?

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

UPDATE: Note that both answers to this question are worth reading, and I would accept both if I could.

推荐答案

感谢stej的点头.

Thanks stej for the nod.

Andrey,powershell有其自己的线程池,并且每个服务线程都保留一个指向运行空间的线程静态指针(System.Management.Automation.Runspaces.Runspace.DefaultRunspace静态成员公开了该静态指针,并且在您的回调中为空引用.)最终,这意味着很难(尤其是在脚本中)使用自己的线程池(由.NET为异步方法提供)来执行脚本块.

Andrey, powershell has its own threadpool and each service thread keeps a threadstatic pointer to a runspace (the System.Management.Automation.Runspaces.Runspace.DefaultRunspace static member exposes this - and would be a null ref in your callbacks.) Ultimately this means it's difficult - especially in script - to use your own threadpool (as is provided by .NET for async methods) to execute scriptblocks.

PowerShell 2.0

无论如何,由于powershell v2完全支持事件处理,因此无需使用此功能:

Regardless, there is no need to play with this as powershell v2 has full support for eventing:

$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),则可以在

If you're stuck on v1 (this is not specifically for you as you mention v2 in the question) you can use my powershell 1.0 eventing snap-in at http://pseventing.codeplex.com/

异步回调

.NET中另一个棘手的地方是异步回调.在Powershell的v1或v2中没有直接帮助您的东西,但是您可以使用一些简单的管道将异步回调转换为事件,然后使用常规事件处理该事件.我在 http://poshcode.org/1382

Another tricky area in .NET is async callbacks. There is nothing directly in v1 or v2 of powershell that can help you here, but you can convert an async callback to an event with some simple plumbing and then deal with that event using regular eventing. I posted a script for this (New-ScriptBlockCallback) at http://poshcode.org/1382

希望这会有所帮助,

-Oisin

这篇关于PowerShell:DownloadFileAsync的运行空间问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆