PowerShell:无法生成新线程

时间:2015-12-24 02:12:59

标签: c# powershell

我试图使用以下命令在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/

1 个答案:

答案 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();