Multithreading 如何停止无限线程

Multithreading 如何停止无限线程,multithreading,powershell,Multithreading,Powershell,我有一个powershell脚本,它使用无限循环创建两个线程(仅作为示例) 当我按下Ctrl+Z时,它试图杀死所有线程。 但它没有成功: 为了创建线程,我使用了BeginInvoke,当我想停止它时,我使用了EndInvoke 问题在于,根据,EndInvoke将等待线程的BeginInvoke完成,但线程不会完成,因为它有无限循环: 等待挂起的异步BeginInvoke完成 当用户按下Ctrl+Z时,如何杀死所有线程 我读到了一个类似的问题: 但它正在使用同样使用EndInvoke的管道

我有一个powershell脚本,它使用无限循环创建两个线程(仅作为示例)

当我按下
Ctrl+Z
时,它试图杀死所有线程。
但它没有成功:

为了创建线程,我使用了
BeginInvoke
,当我想停止它时,我使用了
EndInvoke

问题在于,根据,
EndInvoke
将等待线程的
BeginInvoke
完成,但线程不会完成,因为它有无限循环:

等待挂起的异步BeginInvoke完成

当用户按下
Ctrl+Z
时,如何杀死所有线程

我读到了一个类似的问题:

但它正在使用同样使用
EndInvoke
的管道

这是PowerShell中的一个小脚本,演示了我上面写的内容:

function Invoke-Main(){
    [scriptblock]$code = {
            while($true){
                Start-Sleep 2
                Write-Host "TID: "$([System.Threading.Thread]::CurrentThread.ManagedThreadId)
            }
    }

#requires -Version 2
function Test-KeyPress
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Windows.Forms.Keys[]]
        $Keys
    )

    # use the User32 API to define a keypress datatype
    $Signature = @'
    [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] 
    public static extern short GetAsyncKeyState(int virtualKeyCode); 
'@
    $API = Add-Type -MemberDefinition $Signature -Name 'Keypress' -Namespace Keytest -PassThru

    # test if each key in the collection is pressed
    $Result = foreach ($Key in $Keys)
    {
        [bool]($API::GetAsyncKeyState($Key) -eq -32767)
    }

    # if all are pressed, return true, if any are not pressed, return false
    $Result -notcontains $false
}

    function Kill-AllThreadsOnKeyBreak($Jobs){
        Start-Sleep -Seconds 1
        $ctrlZPressed = $false
        if($host.name -eq 'ConsoleHost'){
            if ([console]::KeyAvailable)
            {
                $key = [system.console]::readkey($true)
                if (($key.modifiers -band [consolemodifiers]"control") -and ($key.key -eq "Z"))
                {
                    $ctrlZPressed = $true
                }
            }
        }
        else{
            $ctrlZPressed = Test-KeyPress -Keys ([System.Windows.Forms.Keys]::ControlKey),([System.Windows.Forms.Keys]::Z)
        }

        if ($ctrlZPressed){
            "Terminating..."
            ForEach ($Job in $Jobs){
                Write-Host "[START] EndInvoke"
                $Job.Thread.EndInvoke($Job.Handle)
                Write-Host "[END] EndInvoke"
                $Job.Thread.Dispose()
                $Job.Thread = $Null
                $Job.Handle = $Null
                $ResultTimer = Get-Date
            }
            Write-Verbose "Termination completed"

        }
    }

    $SleepTimer = 200
    $MaxResultTime = 120
    $MaxThreads = 3

    $ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
    $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
    $RunspacePool.Open()

    $Jobs = @()

    [array]$computerList = @("Computer1", "Computer2")
    foreach($computera in $computerList){
        $PowershellThread = [powershell]::Create().AddScript($code)
        $PowershellThread.RunspacePool = $RunspacePool
        $Handle = $PowershellThread.BeginInvoke()
        $Job = "" | Select-Object Handle, Thread, object
        $Job.Handle = $Handle
        $Job.Thread = $PowershellThread
        $Job.Object = $computer
        $Jobs += $Job
    }

    While (@($Jobs | Where-Object {$_.Handle -ne $Null}).count -gt 0)  {
        Kill-AllThreadsOnKeyBreak $Jobs
        Start-Sleep -Milliseconds $SleepTimer
    }

    $RunspacePool.Close() | Out-Null
    $RunspacePool.Dispose() | Out-Null
}

Invoke-Main

我重新检查了方法
Stop
,将
$Job.Thread.EndInvoke()
替换为
$Job.Thread.Stop()
后,该方法工作正常

可以找到对该命令的引用。
据微软称:

同步停止当前正在运行的命令