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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:09:40  来源:igfitidea点击:

How does threading in powershell work?

multithreadingpowershell

提问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 $jobvariable 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

在 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.

除此之外,您可以执行更高级的操作,例如限制池中并行运行空间的数量,或从当前会话导入函数和变量等。

回答by fcm

The answer, now, is quite simple.

答案,现在,相当简单。

Install-Module -Name ThreadJob -Confirm:$true

$j1= Start-ThreadJob  `
                -FilePath $YourThreadJob `
                -ArgumentList @("A","B")
$j1|get-job
$j1|receive-job