用dot source开始工作

时间:2014-01-06 18:18:10

标签: multithreading powershell arguments

快速故事: 为了试验PowerShell,我试图学习如何有效地多线程化脚本。

现在我知道如何启动作业并将变量传递给我的第二个脚本,但是我已经决定尝试找出如何解决这个问题:

start-job ((Split-Path -parent $PSCommandPath) + "\someScript.ps1") -ArgumentList (,$argList)

进入这个:

start-job (. ((Split-Path -parent $PSCommandPath) + "\someScript.ps1")) -ArgumentList (,$argList)

原因是我在父脚本中声明了一个变量,如下所示:

New-Variable var -value 0 -Option AllScope

并在子脚本中:var = "something" 第一个start-job传递了我的参数,但是孩子没有设置全局'var'变量

第二个没有传递我的参数,但是子脚本设置了父节点中定义的全局变量就好了。 $ argList变量将填充到第二个启动作业中的这行代码,但是在执行该行之后,调试显示$ argList变量为null并且我得到“Start-Job:无法将参数绑定到参数” ScriptBlock'因为它是null。“

为了论证,假设直到所陈述的代码行,变量包含它们应该的数据。

有人可以帮助我解决两次尝试的错误。 谷歌没有给我任何具体的问题答案。 提前感谢我能得到的任何帮助。

编辑: 使用Start-Job (. ((Split-Path -parent $PSCommandPath) + "\someScript.ps1") $argList) 完成我的目标然而我不断得到Start-Job : Cannot bind argument to parameter 'ScriptBlock' because it is null. 即使参数在脚本块中,并且子脚本正在获取并处理参数。

1 个答案:

答案 0 :(得分:0)

当您调用Start-Job时,脚本将在完全独立的范围(PowerShell Runspace)中运行。您无法通过Start-Job直接调用直接调用的脚本。您必须让外部脚本处理通过-ArgumentList传入的参数,然后通过Receive-Job将其返回到原始主机Runspace。

这是一个完整的例子:

$a = 1;
$Job = Start-Job -FilePath C:\test\script.ps1 -ArgumentList $a;


Write-Host -Object "Before: $a"; # Before
Wait-Job -Job $Job;
$a = Receive-Job -Job $Job -Keep;
Write-Host -Object "After: $a"; # After

C:\测试\ script.ps1

以下是文件c:\test\script.ps1的内容:

Write-Output -InputObject (([int]$args[0]) += 5);

线程和运行空间探索

如果您想证明我之前关于Start-Job创建新线程和PowerShell Runspace以及新Thread的观点,请运行此脚本:

# 1. Declare a thread block that retrieves the Runspace ID & ThreadID
$ThreadBlock = { 
    [runspace]::DefaultRunspace.InstanceId.ToString();
    [System.Threading.Thread]::CurrentThread.ManagedThreadId; 
    };

# 2. Start a job and wait for it to finish
$Job = Start-Job -ScriptBlock $ThreadBlock;
[void](Wait-Job -Job $Job);
Receive-Job -Job $Job -Keep;

# 3. Call the same ScriptBlock locally
& $ThreadBlock;

# 4. Note the differences in the Runspace InstanceIDs and ThreadIDs

在完成任务之前接收结果

您可以在PowerShell作业完成之前多次调用Receive-Job来检索结果。以下是理论上如何运作的一个例子:

$ScriptBlock = { 
    1..5 | % { Start-Sleep -Seconds 2; Write-Output -InputObject $_; };
};

$Job = Start-Job -ScriptBlock $ScriptBlock;

while ($Job.JobStateInfo.State -notin ([System.Management.Automation.JobState]::Completed,[System.Management.Automation.JobState]::Failed)) {
    Start-Sleep -Seconds 3;
    $Results = Receive-Job -Job $Job;
    Write-Host -Object ('Received {0} items: {1}' -f $Results.Count, ($Results -join ' '));
}