Multithreading powershell中的线程是如何工作的?

Multithreading powershell中的线程是如何工作的?,multithreading,powershell,Multithreading,Powershell,我想将一些文件解析操作与powershell中的网络活动并行化。用谷歌快速搜索, 开始线程看起来像一个解决方案,但是: 术语“启动线程”不能识别为cmdlet、函数、脚本文件或可操作程序的名称。请检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试 我试着开始工作时也发生了同样的事情 我还试着摆弄一下 所以,我认为最好是知道我在使用start线程时做错了什么,因为它似乎适用于其他人。我使用v2.0,不需要向下兼容。Powershell没有名为Start Thread的内置命令 但是,V

我想将一些文件解析操作与powershell中的网络活动并行化。用谷歌快速搜索, 开始线程看起来像一个解决方案,但是:

术语“启动线程”不能识别为cmdlet、函数、脚本文件或可操作程序的名称。请检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试

我试着开始工作时也发生了同样的事情

我还试着摆弄一下


所以,我认为最好是知道我在使用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