我试图使用以下命令在PowerShell的命令行中生成一个新线程:
$t = New-Object System.Threading.Thread ([System.Threading.ThreadStart]{
Write-Host "Hello World"
});
$t.Start();
会出现一个对话框,显示“Powershell已停止工作”。
我想使用我自己的Job
类,用C#编写,带有start,pause,continue和stop方法。它使用了几个WaitHandles
来与新的Thead
实例一起实现此目的。
我知道Start-Job
等,但想使用真正的线程。
任何方式?
编辑:似乎有办法https://davewyatt.wordpress.com/2014/04/06/thread-synchronization-in-powershell/
答案 0 :(得分:1)
更新我已将以下内容打包到名为PSRunspacedDelegate
的模块中,您可以使用Install-Package PSRunspacedDelegate
进行安装。您可以找到documentation on GitHub。
Adam Driscoll's PowerShell Parallel Foreach解释说运行PowerShell代码的线程必须有Runspace
。
换句话说,[Runspace]::DefaultRunspace
不能为空。
我最终编写了一个RunspacedDelegateModule.psm1
模块,其功能New-RunspacedDelegate
可以完成工作。
Add-Type -Path "$PSScriptRoot\RunspacedDelegateFactory.cs"
Function New-RunspacedDelegate(
[Parameter(Mandatory=$true)][System.Delegate]$Delegate,
[Runspace]$Runspace=[Runspace]::DefaultRunspace) {
[PowerShell.RunspacedDelegateFactory]::NewRunspacedDelegate($Delegate, $Runspace)
}
RunspacedDelegateFactory.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Management.Automation.Runspaces;
namespace PowerShell
{
public class RunspacedDelegateFactory
{
public static Delegate NewRunspacedDelegate(Delegate _delegate, Runspace runspace)
{
Action setRunspace = () => Runspace.DefaultRunspace = runspace;
return ConcatActionToDelegate(setRunspace, _delegate);
}
private static Expression ExpressionInvoke(Delegate _delegate, params Expression[] arguments)
{
var invokeMethod = _delegate.GetType().GetMethod("Invoke");
return Expression.Call(Expression.Constant(_delegate), invokeMethod, arguments);
}
public static Delegate ConcatActionToDelegate(Action a, Delegate d)
{
var parameters =
d.GetType().GetMethod("Invoke").GetParameters()
.Select(p => Expression.Parameter(p.ParameterType, p.Name))
.ToArray();
Expression body = Expression.Block(ExpressionInvoke(a), ExpressionInvoke(d, parameters));
var lambda = Expression.Lambda(d.GetType(), body, parameters);
var compiled = lambda.Compile();
return compiled;
}
}
}
我注意到如果我使用Write-Host
它仍会崩溃,但Out-File
似乎没问题。
以下是如何使用它:
Import-Module RunspacedDelegateModule;
$writeHello = New-RunspacedDelegate ([System.Threading.ThreadStart]{
"$([DateTime]::Now) hello world" | Out-File "C:\Temp\log.txt" -Append -Encoding utf8
});
$t = New-Object System.Threading.Thread $writeHello;
$t.Start();