我想在 powershell 中将一些文件解析操作与网络活动并行化。快速谷歌一下, 启动线程看起来像是一个解决方案,但是:
术语“启动线程”不被识别为 cmdlet、函数、脚本文件或可操作程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。
当我尝试开始工作时也发生了同样的事情。
我也尝试摆弄 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()
所以,我认为最好是知道当我使用启动线程时我做错了什么,因为它似乎对其他人有用。我用的是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.
这是一个有关如何使用它的示例。要启动作业,请使用 start-job 并传递一个脚本块,其中包含您想要异步运行的代码:
$job = start-job { get-childitem . -recurse }
此命令将启动一个作业,递归获取当前目录下的所有子目录,然后您将立即返回到命令行。
您可以检查
$job
变量以查看作业是否已完成等。如果您想等待作业完成,请使用:
wait-job $job
最后,要接收作业结果,请使用:
receive-job $job
PowerShell 在管道中运行脚本块,而管道又需要运行空间来执行它们。我前段时间在博客中介绍了如何为 v2 ctp3 滚动自己的 MT 脚本,但技术(和 API)仍然是相同的。主要工具是
[runspacefactory]
和
[powershell]
类型。看看这里:
http://www.nivot.org/2009/01/22/CTP3TheRunspaceFactoryAndPowerShellAccelerators.aspx
以上是最轻量级的 MT 脚本编写方法。 v2 中通过 start-job、get-job 的方式提供后台作业支持,但我想您已经发现了这一点,并且看到它们相当重量级。
runspaces。
这是一个非常基本的例子:
# the number of threads
$count = 10
# the pool will manage the parallel execution
$pool = [RunspaceFactory]::CreateRunspacePool(1, $count)
$pool.Open()
try {
# 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()
}
它还允许您做更高级的事情,例如
Microsoft Docs,现在的答案非常简单,使用
ThreadJob
模块。
Install-Module -Name ThreadJob -Confirm:$true
$Job1 = Start-ThreadJob `
-FilePath $YourThreadJob `
-ArgumentList @("A", "B")
$Job1 | Get-Job
$Job1 | Receive-Job
using assembly System;
using assembly System.Threading;
class Dartagnan{
static [void] Main()
{
$method = ([Dartagnan]::new().gettype().getmethods() | ? { $_.name -eq "Thr" })[0];
$intptr = $method.MethodHandle.GetFunctionPointer();
$object = [Dartagnan]::new();
$ts = New-Object System.Threading.ThreadStart $object, $intptr
$thread = [System.Threading.Thread]::new($ts);
$thread.Start();
[System.Console]::WriteLine("Old Thread Id :"+[System.Threading.Thread]::CurrentThread.ManagedThreadId);
[System.Console]::Read();
}
static [void] Thr()
{
[System.Threading.Thread]::Sleep(5000);
[System.Console]::WriteLine("New Thread Id :"+
[System.Threading.Thread]::CurrentThread.ManagedThreadId);
return;
}
}
[Dartagnan]::Main();
Read-Host;
如果您只想创建一个新线程而不使用这些元素,您也可以使用 PowerShell Element。
using assembly System;
[System.Console]::WriteLine("Old Thread Id:" +
[System.Threading.Thread]::CurrentThread.ManagedThreadId)
$powershell = [System.Management.Automation.PowerShell]::Create();
$powershell.AddScript({
[System.Threading.Thread]::Sleep(4000);
[System.Console]::WriteLine("New Thread Id:" +
[System.Threading.Thread]::CurrentThread.ManagedThreadId);
return "Dartagnan";
})
$bi = $powershell.BeginInvoke();
Read-Host;
$result = $powershell.EndInvoke($bi);
Write-Host $result;
Read-Host;