Multithreading powershell中的线程是如何工作的?
我想将一些文件解析操作与powershell中的网络活动并行化。用谷歌快速搜索, 开始线程看起来像一个解决方案,但是: 术语“启动线程”不能识别为cmdlet、函数、脚本文件或可操作程序的名称。请检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试 我试着开始工作时也发生了同样的事情 我还试着摆弄一下Multithreading powershell中的线程是如何工作的?,multithreading,powershell,Multithreading,Powershell,我想将一些文件解析操作与powershell中的网络活动并行化。用谷歌快速搜索, 开始线程看起来像一个解决方案,但是: 术语“启动线程”不能识别为cmdlet、函数、脚本文件或可操作程序的名称。请检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试 我试着开始工作时也发生了同样的事情 我还试着摆弄一下 所以,我认为最好是知道我在使用start线程时做错了什么,因为它似乎适用于其他人。我使用v2.0,不需要向下兼容。Powershell没有名为Start Thread的内置命令 但是,V
所以,我认为最好是知道我在使用start线程时做错了什么,因为它似乎适用于其他人。我使用v2.0,不需要向下兼容。Powershell没有名为Start Thread的内置命令 但是,V2.0确实有PowerShell作业,它可以在后台运行,可以被视为相当于线程。您可以使用以下命令来处理作业:
Name Category Synopsis
---- -------- --------
Start-Job Cmdlet Starts a Windows PowerShell background job.
Get-Job Cmdlet Gets Windows PowerShell background jobs that are running in the current ...
Receive-Job Cmdlet Gets the results of the Windows PowerShell background jobs in the curren...
Stop-Job Cmdlet Stops a Windows PowerShell background job.
Wait-Job Cmdlet Suppresses the command prompt until one or all of the Windows PowerShell...
Remove-Job Cmdlet Deletes a Windows PowerShell background job.
下面是一个如何使用它的示例。要启动作业,请使用“启动作业”并传递包含要异步运行的代码的脚本块:
$job = start-job { get-childitem . -recurse }
此命令将启动一个作业,该作业递归地获取当前目录下的所有子项,您将立即返回到命令行
您可以检查$job
变量以查看作业是否已完成等。如果要等待作业完成,请使用:
wait-job $job
最后,要接收作业的结果,请使用:
receive-job $job
你不能像这样直接使用线程,但也不能因为你的尝试而受到指责,因为一旦整个BCL都摆在你面前,指望它大部分都能工作就不那么愚蠢了:) PowerShell在管道中运行脚本块,而管道又需要运行空间来执行脚本块。不久前,我在博客中谈到了如何为v2ctp3推出自己的MT脚本,但技术(和API)仍然是一样的。主要工具是
[runspacefactory]
和[powershell]
类型。请看这里:
以上是处理MT脚本的最轻量级的方法。v2中有背景作业支持,例如启动作业、获取作业,但我想您已经注意到了这一点,并看到它们相当重要。在MSDN上的powershell中有一篇关于背景作业的文章 您还可以在powershell中阅读有关作业的内容
> help about_Jobs
我有一篇关于如何对任何给定的powershell脚本进行多线程处理的博客文章
享受吧 最接近线程的东西是PowerShell,它的性能远远高于作业 下面是一个非常基本的例子:
# the number of threads
$count = 10
# the pool will manage the parallel execution
$pool = [RunspaceFactory]::CreateRunspacePool(1, $count)
try {
$pool.Open()
# create and run the jobs to be run in parallel
$jobs = New-Object object[] $count
for ($i = 0; $i -lt $count; $i++) {
$ps = [PowerShell]::Create()
$ps.RunspacePool = $pool
# add the script block to run
[void]$ps.AddScript({
param($Index)
Write-Output "Index: $index"
})
# optional: add parameters
[void]$ps.AddParameter("Index", $i)
# start async execution
$jobs[$i] = [PSCustomObject]@{
PowerShell = $ps
AsyncResult = $ps.BeginInvoke()
}
}
foreach ($job in $jobs) {
try {
# wait for completion
[void]$job.AsyncResult.AsyncWaitHandle.WaitOne()
# get results
$job.PowerShell.EndInvoke($job.AsyncResult)
}
finally {
$job.PowerShell.Dispose()
}
}
}
finally {
$pool.Dispose()
}
除此之外,您还可以执行更高级的操作,如限制池中并行运行空间的数量,或从当前会话导入函数和变量等。现在,操作非常简单
Install-Module -Name ThreadJob -Confirm:$true
$j1= Start-ThreadJob `
-FilePath $YourThreadJob `
-ArgumentList @("A","B")
$j1|get-job
$j1|receive-job
这个剧本太棒了!非常感谢你的发帖。这篇文章不再有了。-1对于没有任何解释的链接,链接像往常一样被删除,这个答案就没有用了。没有任何上下文的链接不被允许的确切原因现在看来是链接备份了。Start-Job实际上启动了一个新的Powershell会话,而且它很重。它不会启动线程。start-Job不会捕获任何环境状态,没有局部变量、函数或模块导入,具有巨大的开销,是典型的吮吸式PowerShell API。如果.NET TPL可以与PS runspace strategytl的一些调度一起使用,这将非常有帮助;dr:
receive作业(wait作业($a=start作业{“heyo!”}));删除作业$a
或$a=start job{“heyo!”};等待工作一美元;一份工作可获$1;删除作业$a
另请注意,如果在作业完成之前调用接收作业
,则可能什么也得不到。另外(获取作业$a)。jobstateinfo.state代码>:D 9年7个月。那么这有什么用呢?使用不同的参数启动同一脚本的子shell?是的,您可以根据需要启动任意多个线程,当然不仅仅是调用您自己(我的原始示例非常递归)
Install-Module -Name ThreadJob -Confirm:$true
$j1= Start-ThreadJob `
-FilePath $YourThreadJob `
-ArgumentList @("A","B")
$j1|get-job
$j1|receive-job