gpt4 book ai didi

PowerShell 和 Net.WebClient。需要澄清工作行为

转载 作者:行者123 更新时间:2023-12-04 07:47:26 25 4
gpt4 key购买 nike

假设我正在使用 Net.WebClient 的 DownloadFile 方法下载大文件:

$uri1 = "blabla.com/distro/blabla_2gb.exe"
$localfile1 = "$Env:userprofile\Downloads\blabla_2gb.exe"

$wbcl = New-Object System.Net.WebClient
$wbcl.DownloadFile($uri1, $localfile1)
$wbcl.Dispose()
在这种情况下,我可以随时使用 Alt + F4 来终止我的脚本。下载过程将停止,$wbcl 将被自动处理。
但如果我在工作中做同样的事情:
Start-Job -ScriptBlock `
{
#SAME CODE AS ABOVE
} | Out-Null

#SOME PARALLEL ACTIVITY

Wait-Job -ID 1 | Out-Null
即使父脚本关闭,下载也会继续。根据文档,终止父脚本将导致所有相应作业的停止。那为什么还要继续下载呢?
附言我知道我可以通过使用 DownloadFileAsync 避免在这里开始工作,但我真的很想了解这种机制 :)

最佳答案

我相信这是因为执行已流入 .NET 方法,PowerShell 不再对其进行控制。
例如,如果我运行...

Start-Job -ScriptBlock { Start-Sleep -Seconds 30 }
...或者...
Start-Job -ScriptBlock { while ($true) { } }
...我可以在任务管理器中看到有两个 PowerShell 进程。如果我然后单击 PowerShell 窗口的关闭按钮(Alt + F4 对我不起作用),两个进程都会立即消失。
如果我跑...
Start-Job -ScriptBlock { [System.Threading.Thread]::Sleep([TimeSpan]::FromSeconds(30)) }
...然后我还在任务管理器中看到两个 PowerShell 进程。但是,关闭 PowerShell 窗口后,只有一个 PowerShell 进程立即消失;另一个在 30 秒的剩余时间后消失。有趣的是,如果我运行 exit不是关闭 PowerShell 窗口,而是在作业完成之前窗口保持打开状态并闪烁光标。
另一种观察方式是使用 Stop-Job .在这个脚本中...
$job = Start-Job -ScriptBlock { Start-Sleep -Seconds 30 }
Start-Sleep -Seconds 1 # Give the job time to transition to the Running state
$job | Stop-Job
... Stop-Job立即返回,而在此脚本中...
$job = Start-Job -ScriptBlock { [System.Threading.Thread]::Sleep([TimeSpan]::FromSeconds(30)) }
Start-Sleep -Seconds 1 # Give the job time to transition to the Running state
$job | Stop-Job
...需要 30 秒。
我不太熟悉 PowerShell 执行的低级工作原理,但是在父进程关闭时的前两个片段中,作业进程正在运行 PowerShell 代码,因此它将能够在任意点中断并响应父进程的终止信号。在第三个片段中,作业进程正在运行 .NET 代码,等待方法返回。我不能说运行 .NET 代码的线程是与父进程通信的同一线程,还是它是不同的线程,PowerShell 只是尊重 the dangers of aborting another thread。 (PowerShell 在作业之外运行时中断 DownloadFile() 以退出是没有问题的,这表明前者),但结果是相同的:作业进程不会终止,因为它“卡”在 .NET 代码中,直到它完成.
这也可能与执行 .NET 方法时 Ctrl + C 不(立即)工作的原因有关。见 Powershell AcceptTcpClient() cannot be interrupted by Ctrl-C .
还有一点:确保您调用 Dispose()finally 内 block 以确保它确实被调用,即使 DownloadFile()抛出异常...
$wbcl = New-Object System.Net.WebClient
try
{
$wbcl.DownloadFile($uri1, $localfile1)
}
finally
{
$wbcl.Dispose()
}

关于PowerShell 和 Net.WebClient。需要澄清工作行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67143426/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com