Multithreading – runspace problem with PowerShell: downloadfileasync

I need to download files using webclient in power shell 2.0. I want to display the download progress, so I do this:

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

I received an error. There is no runspace available to run scripts in this thread This is logical for the code in the $downloadprogress handler However, how do you provide runspaces for threads that (possibly) belong to ThreadPool?

Update: Please note that the answers to this question are worth reading and I will accept them if I can

Solution

Thanks, stej nodded

Andrey, PowerShell has its own thread pool, Each service thread maintains a thread pointer to a runspace (system.management.automation.runspaces.runspace.defaultrunspace static members expose this - and will be an empty reference in your callback) ultimately, this means that it is difficult (especially in scripts) to execute script blocks using its own thread pool (provided by. Net for asynchronous methods)

PowerShell 2.0

In any case, there is no need to play this, because PowerShell V2 fully supports event occurrence:

$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

If you insist on V1 (this is not specifically for you to mention the problems in V2), you can use my PowerShell 1.0 event snap in to http://pseventing.codeplex.com/

Asynchronous callback

. Net is asynchronous callback Nothing directly in V1 or V2 PowerShell can help you here, but you can convert an asynchronous callback to a simple pipeline event, and then handle the event using regular events I am here http://poshcode.org/1382 Published a script (New scriptblockcallback)

I hope it helps,

-Oisin

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>