Почему мой вызов Receive-Job зависает при вызове scriptblock?

#powershell

#powershell

Вопрос:

Мой код не может достичь конечной строки вывода:

 $downloadCommand = { 
    $Response = Invoke-WebRequest -Uri "$someurl" -OutFile "$somelocation" 
    0 
}

$job = Start-Job $downloadCommand

$sleeptime=10

While(Get-Job -State "Running")
{
    #Get-Job -State "Running"
    Start-Sleep -Seconds $sleeptime
}

Get-Job | Wait-Job

$result = Receive-Job -Job $job # <=== gets stuck here

Write-Host "Can't reach here"
  

Есть идеи, что я здесь делаю не так? Я знаю, что загрузка работает нормально, и она, безусловно, выходит из цикла while.

Комментарии:

1. Не могли бы вы, пожалуйста, определить или уточнить get's stuck here ? Выполняется ли скрипт непрерывно в этот момент или что происходит?

2. Скрипт просто зависает и продолжает выполняться непрерывно, пока я его не убью.

3. Создается / записывается ли файл в $somelocation ? Если нет, попробуйте изменить Invoke-WebRequest вызов на Invoke-WebRequest -Uri "$someurl" -OutFile "$somelocation" -UseBasicParsing

4. Да, файл успешно записывается / загружается в это местоположение. Это zip-файл размером 180 МБ. Когда я закомментирую строку, которая застряла, остальная часть моего скрипта продолжается, и я могу распаковать этот файл. Как бы то ни было, я запускаю сценарий powershell таким образом (вызывается из .bat-скрипта) .: powershell -NoProfile -ExecutionPolicy Unrestricted -command C:foo.ps1

Ответ №1:

Как ни странно, я не могу заставить ваш пример зависать бесконечно. Может быть, вы загружаете какой-то огромный файл? Возможно, ваш сервер назначения обрабатывает неопределенно долго?

Я изменил ваш скрипт, чтобы получить больше информации.

Если вы проверяете состояние задания и ждете с помощью Start-Sleep — в вашем скрипте нет необходимости в Wait-Job.

Правильный способ ожидания задания:

 $downloadCommand = { 
    Invoke-WebRequest -Uri "$someurl" -OutFile "$somelocation";
}

$job = Start-Job $downloadCommand;
    
$sleepTime = 10;

while ((Get-Job | Where-Object Id -eq $job.Id).State -eq "Running")
{
    Write-Host "Waiting next $sleepTime seconds for job $($job.Id) to finish...";
    Start-Sleep -Seconds $sleepTime;
}

Receive-Job $job;
  

Кстати, начиная с Powershell 7.0, вы можете использовать Foreach-Object -Parallel ( https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7)

Комментарии:

1. Это zip-файл размером 180 МБ. Что касается ненужного задания ожидания, я согласен с вами. На самом деле у меня его там изначально не было, и я просто разместил его там для наглядности. Итак, я скопировал ваш код и завернул инструкции вывода в Receive-Job: Write-Host "-- Download Stopped." Receive-Job $job; Write-Host "-- Download Completed." Последний вывод, который я вижу, это «— Загрузка остановлена». и выполнение зависает здесь, пока я не завершу его. И спасибо за предложение, но, к сожалению, мой компьютер все еще зависает на версии 5.1.