在 Powershell 中正确使用 ForEach -parallel?
Correct usage of ForEach -parallel in Powershell?
我想处理大量 URL 并抓取 *.jpg 文件位置。
问题是第二个 foreach 中的 $entry
不是线程安全的。
该脚本引发了数百个错误,因为 $entry
被一遍又一遍地覆盖。
当我将内部 foreach
移到 ForEach-Object
之外时,它工作正常但速度非常慢。
如何在我的 ForEach-Object
中正确处理拆分输出而不会出现这些错误?
$array
仅包含大量 URL
$clean_img_array
是运算的输出数组
$tmpArray
是对 $clean_img_array
的引用,以便在并行 ForEach 中使用它
错误:
InvalidOperation:
Line |
14 | [void]$tmpArray:clean_img_array.Add($entry);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| You cannot call a method on a null-valued expression.
片段:
$clean_img_array = [System.Collections.ArrayList]@();
$array | ForEach-Object -Parallel {
$web = Invoke-RestMethod $_;
$i=1;
foreach($entry in $web.Split("`"")){
echo $entry;
if($entry.IndexOf(".jpg") -ne -1 -And $entry.IndexOf("http") -ne -1){
if($entry.IndexOf("?") -ne -1){
$tmpArray = $using:clean_img_array;
[void]$tmpArray.Add($entry.Substring(0, $entry.IndexOf('?')));
}else{
$tmpArray = $using:Clean_img_array;
[void]$tmpArray:clean_img_array.Add($entry);
}
}
}
} -ThrottleLimit 20
这是一个简单的例子。 $a 和 $b 都是数组。 $b 是并行循环的结果。就像文档中的 example 12。
$a = 1..10
$b = $a | foreach-object -parallel { $_ + 1 }
$b
2
3
4
5
6
7
8
9
10
11
感谢支持!
我将 @js2012 的答案与我自己的答案结合起来。
单独的 return 并没有解决 $entry
的线程取消保存行为,但显然理清了工作流程。
但是我使用了 .foreach
的内联版本和管道变量 $_
在我看来是线程安全的。 运行 现在很有魅力,而且条目数超过 200 万的速度也非常快。
$array
保存要处理的 URL
$clean_img_array
return抓取的图片网址
$clean_img_array = $array | ForEach-Object -Parallel {
$web = Invoke-RestMethod $_;
$web.Split("`"").foreach({
if($_ -ne $null){
if($_.IndexOf(".jpg") -ne -1 -And $_.IndexOf("http") -ne -1){
if($_.IndexOf("?") -ne -1){
return $_.Substring(0, $entry.IndexOf('?'));
}else{
return $_;
}
}
}
});
} -ThrottleLimit 25
我想处理大量 URL 并抓取 *.jpg 文件位置。
问题是第二个 foreach 中的 $entry
不是线程安全的。
该脚本引发了数百个错误,因为 $entry
被一遍又一遍地覆盖。
当我将内部 foreach
移到 ForEach-Object
之外时,它工作正常但速度非常慢。
如何在我的 ForEach-Object
中正确处理拆分输出而不会出现这些错误?
$array
仅包含大量 URL$clean_img_array
是运算的输出数组$tmpArray
是对$clean_img_array
的引用,以便在并行 ForEach 中使用它
错误:
InvalidOperation:
Line |
14 | [void]$tmpArray:clean_img_array.Add($entry);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| You cannot call a method on a null-valued expression.
片段:
$clean_img_array = [System.Collections.ArrayList]@();
$array | ForEach-Object -Parallel {
$web = Invoke-RestMethod $_;
$i=1;
foreach($entry in $web.Split("`"")){
echo $entry;
if($entry.IndexOf(".jpg") -ne -1 -And $entry.IndexOf("http") -ne -1){
if($entry.IndexOf("?") -ne -1){
$tmpArray = $using:clean_img_array;
[void]$tmpArray.Add($entry.Substring(0, $entry.IndexOf('?')));
}else{
$tmpArray = $using:Clean_img_array;
[void]$tmpArray:clean_img_array.Add($entry);
}
}
}
} -ThrottleLimit 20
这是一个简单的例子。 $a 和 $b 都是数组。 $b 是并行循环的结果。就像文档中的 example 12。
$a = 1..10
$b = $a | foreach-object -parallel { $_ + 1 }
$b
2
3
4
5
6
7
8
9
10
11
感谢支持!
我将 @js2012 的答案与我自己的答案结合起来。
单独的 return 并没有解决 $entry
的线程取消保存行为,但显然理清了工作流程。
但是我使用了 .foreach
的内联版本和管道变量 $_
在我看来是线程安全的。 运行 现在很有魅力,而且条目数超过 200 万的速度也非常快。
$array
保存要处理的 URL$clean_img_array
return抓取的图片网址$clean_img_array = $array | ForEach-Object -Parallel { $web = Invoke-RestMethod $_; $web.Split("`"").foreach({ if($_ -ne $null){ if($_.IndexOf(".jpg") -ne -1 -And $_.IndexOf("http") -ne -1){ if($_.IndexOf("?") -ne -1){ return $_.Substring(0, $entry.IndexOf('?')); }else{ return $_; } } } }); } -ThrottleLimit 25