multithreading powershell中的线程如何工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3325911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does threading in powershell work?
提问by Caesar
I want to parallelize some file-parsing actions with network activity in powershell. Quick google for it, start-thread looked like a solution, but:
我想在 powershell 中将一些文件解析操作与网络活动并行化。快速谷歌一下,开始线程看起来像一个解决方案,但是:
The term 'start-thread' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
术语“启动线程”不被识别为 cmdlet、函数、脚本文件或可运行程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。
The same thing happened when I tried start-job.
当我尝试开始工作时发生了同样的事情。
I also tried fiddling around with System.Threading.Thread
我也尝试摆弄System.Threading.Thread
[System.Reflection.Assembly]::LoadWithPartialName("System.Threading")
#This next errors, something about the arguments I can't figure out from the documentation of .NET
$tstart = new-object System.Threading.ThreadStart({DoSomething})
$thread = new-object System.Threading.Thread($tstart)
$thread.Start()
So, I think the best would be to know what I do wrong when I use start-thread, because it seems to work for other people. I use v2.0 and I don't need downward compatibility.
所以,我认为最好的办法是知道我在使用 start-thread 时做错了什么,因为它似乎对其他人有用。我使用 v2.0,不需要向下兼容。
回答by driis
Powershell does not have a built-in command named Start-Thread.
Powershell 没有名为 Start-Thread 的内置命令。
V2.0 does, however, have PowerShell jobs, which can run in the background, and can be considered the equivalent of a thread. You have the following commands at your disposal for working with jobs:
然而,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.
Here is an example on how to work with it. To start a job, use start-job and pass a script block which contains the code you want run asynchronously:
这是有关如何使用它的示例。要启动作业,请使用 start-job 并传递一个包含您要异步运行的代码的脚本块:
$job = start-job { get-childitem . -recurse }
This command will start a job, that gets all children under the current directory recursively, and you will be returned to the command line immediately.
此命令将启动一个作业,该作业以递归方式获取当前目录下的所有子项,您将立即返回到命令行。
You can examine the $job
variable to see if the job has finished, etc. If you want to wait for a job to finish, use:
您可以检查$job
变量以查看作业是否已完成等。如果您想等待作业完成,请使用:
wait-job $job
Finally, to receive the results from a job, use:
最后,要接收作业的结果,请使用:
receive-job $job
回答by x0n
You can't use threads directly like this, but you can't be blamed for trying since once the whole BCL is lying in front of you it's not entirely silly to expect most of it to work :)
你不能像这样直接使用线程,但你不能因为尝试而受到责备,因为一旦整个 BCL 摆在你面前,期望它的大部分工作并不完全是愚蠢的:)
PowerShell runs scriptblocks in pipelines which in turn require runspaces to execute them. I blogged about how to roll your own MT scripts some time ago for v2 ctp3, but the technique (and API) is still the same. The main tools are the [runspacefactory]
and [powershell]
types. Take a look here:
PowerShell 在管道中运行脚本块,而管道又需要运行空间来执行它们。前段时间我写了一篇关于如何为 v2 ctp3 推出自己的 MT 脚本的博客,但技术(和 API)仍然相同。主要工具是[runspacefactory]
和[powershell]
类型。看看这里:
http://www.nivot.org/2009/01/22/CTP3TheRunspaceFactoryAndPowerShellAccelerators.aspx
http://www.nivot.org/2009/01/22/CTP3TheRunspaceFactoryAndPowerShellAccelerators.aspx
The above is the most lightweight way to approach MT scripting. There is background job support in v2 by way of start-job, get-job but I figured you already spotted that and saw that they are fairly heavyweight.
以上是处理 MT 脚本的最轻量级的方法。v2 中通过 start-job、get-job 的方式提供后台作业支持,但我想你已经发现了这一点,并且看到它们相当重量级。
回答by Ryan Witschger
I have a blog article on how you can multithread any given powershell script.
我有一篇关于如何对任何给定的 powershell 脚本进行多线程处理的博客文章。
Multithreading with Jobs in PowerShell
Enjoy!
享受!
回答by Eric Weilnau
There is an article about background jobs in powershell on MSDN at http://msdn.microsoft.com/en-us/library/dd878288(VS.85).aspx.
MSDN 上有一篇关于 powershell 后台作业的文章,网址为http://msdn.microsoft.com/en-us/library/dd878288(VS.85).aspx。
You can also read about jobs in powershell itself.
您还可以在 powershell 本身中阅读有关作业的信息。
> help about_Jobs
回答by marsze
The thing that comes closest to threads and is way more performant than jobs is PowerShell runspaces.
最接近线程并且比作业性能更高的东西是 PowerShell 运行空间。
Here is a very basic example:
这是一个非常基本的例子:
# 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()
}
Beyond that, you can do more advanced things like throttle the number of parallel runspaces on the pool, or import functions and variables from the current session etc.
除此之外,您可以执行更高级的操作,例如限制池中并行运行空间的数量,或从当前会话导入函数和变量等。