[英]Powershell runspace multithreading question
In the example below, even though I cap the concurrent threads at 50, the code will (within seconds) process and go down to the foreach ($thread in $threads).在下面的示例中,即使我将并发线程限制为 50,代码仍将(在几秒钟内)处理并将 go 向下传递到 foreach($threads in $threads)。
Is this expected behavior because the runspace pool is doing wizardry in the background and will store all 2000 thread objects in memory, but only allow 50 active at any time?这是预期的行为,因为运行空间池在后台执行魔法并将所有 2000 个线程对象存储在 memory 中,但在任何时候只允许 50 个活动?
The reason behind my question is that I'm trying to figure out why the processing is not nearly as fast as it should be.我的问题背后的原因是我试图弄清楚为什么处理速度不如预期的那么快。
$runspacePool = [runspacefactory]::CreateRunspacePool(
1, #Min Runspaces
50 #Max Runspaces
);
$remoteMailboxes = Get-RemoteMailbox -Resultsize 2000;
foreach ($remoteMailbox in $remoteMailboxes)
{
$powerShell = [powershell]::Create($sessionState);
$powerShell.RunspacePool = $runspacePool;
[void]$powerShell.AddScript({
Param ($alias<#, $paths, $filters, $exclusionsArrNoAsterisks#>)
[pscustomobject]@{
alias = $alias;
} | Out-Null;
# a bunch of processing that takes 30 seconds happens here
return $returnedMailboxObj;
}) # end of add script
$powerShell.AddParameter('alias', $remoteMailbox.Alias) | Out-Null;
$returnVal = $powerShell.BeginInvoke();
$temp = "" | Select powerShell,returnVal,server;
$temp.powerShell = $powerShell;
$temp.returnVal = $returnVal;
$temp.server = $server;
$threadStartTime = [DateTime]::Now.ToLongTimeString();
$tuple = [tuple]::create([string]$server, [DateTime]$threadStartTime);
$threadTimerTemp.Add($tuple) | Out-Null;
$threads.Add($temp) | Out-Null;
}
foreach ($thread in $threads)
{
$threadsTemp.Add($thread) | Out-Null;
}
$endInvokeArr = New-Object System.Collections.ArrayList;
$threadsCompleted = New-Object System.Collections.ArrayList;
$threadsNotCompleted = New-Object System.Collections.ArrayList;
$threadsNotCompleted.Add("PlaceHolder") | Out-Null;
while ($threadsTemp.Count -gt 0)
{
$threadsNotCompleted.Clear();
Write-Host "Updated thread count" $threadsTemp.Count;
for ($i = 0; $i -lt $threadsTemp.Count; $i++)
{
$threadIsCompleted = $threadsTemp[$i].returnVal.IsCompleted;
if ($threadIsCompleted -eq $false)
{
#$completed = $false;
$threadsNotCompleted.Add($thread) | Out-Null;
# Ignore
}
else
{
$threadHandle = $threadsTemp[$i].returnVal.AsyncWaitHandle.Handle;
$threadsCompleted.Add($threadHandle) | Out-Null;
$endInvoke = $threadsTemp[$i].PowerShell.EndInvoke($threadsTemp[$i].returnVal);
$endInvokeArr.Add($endInvoke) | Out-Null;
$threadsTemp.Remove($threadsTemp[$i]);
$i++;
}
}
Write-Host "endInvokeArrCount" $endInvokeArr.Count;
Write-Host "Threads completed count: " $threadsCompleted.Count;
Write-Host "Threads count" $threadsTemp.Count;
sleep -Milliseconds 100;
} # while end
Is this expected behavior because the runspace pool is doing wizardry in the background and will store all 2000 thread objects in memory, but only allow 50 active at any time?
这是预期的行为,因为运行空间池在后台执行魔法并将所有 2000 个线程对象存储在 memory 中,但在任何时候只允许 50 个活动?
The method PowerShell.BeginInvoke()
could as well have been called PowerShell.ScheduleWorkForWheneverARunspaceIsReadyInTheFuture()
- that is, BeginInvoke
doesn't actual do any work before returning to the caller - it simply:方法
PowerShell.BeginInvoke()
也可以称为PowerShell.ScheduleWorkForWheneverARunspaceIsReadyInTheFuture()
- 也就是说, BeginInvoke
在返回给调用者之前实际上并没有做任何工作 - 它很简单:
IAsyncResult
object you briefly store in $returnval
) for the "work order" scheduled$returnval
中的IAsyncResult
object ) These relatively simple steps can obviously be completed much faster than actually executing the associated code, so it's not actually that unusual to be able to begin (ie "schedule") many more executions than can be run concurrently - heck, the runspace pool might not even have started executing the first request by the time you've scheduled the remaining 1999.这些相对简单的步骤显然可以比实际执行相关代码更快地完成,因此能够开始(即“调度”)比并发运行更多的执行实际上并不少见 - 哎呀,运行空间池可能不会甚至在您安排剩余的 1999 年时已经开始执行第一个请求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.