Search code examples
powershellstart-jobcreatethread

Why can't a thread created by PowerShell execute script functions?


I have a script function that calls. net to manipulate word documents. It works. Now I want to create a sub-thread to execute it, and then the main thread decides whether it completes or exceeds the specified time, and ends it after that time. As shown in the code,It does not execute functions in the block of $node code, but instead $task1 executes the cmdlet. Why is that? How can I fulfill my needs?

try{
# $cb is a instance of class,scan is the function I want to invoke.
    $code = { $cb.Scan($PrepareFileName, $NailDirName, $HtmlFileName) }
#    $task1 = { Start-Sleep -Seconds 9; Get-Service }
    $newThread = [PowerShell]::Create().AddScript($code)
    $handleTh = $newThread.BeginInvoke()
    $nTimes = 0;
    do
    {
        $nTimes++;
        if($handleTh.IsCompleted -or $nTimes -gt 10)
        {
          break;  
        }
        Start-Sleep -Milliseconds 500

    } while($true)

    $newThread.EndInvoke($handleTh)
    $newThread.Runspace.Close()
    $newThread.Dispose()

}catch{

}

Solution

  • You need to create a runspaceand it to the PowerShell object. Check this microsoft "tutorial" for using runspaces in a correct manner. The link also explains how to use runspace pools, and script block arguments.

    try{
        # $cb is a instance of class,scan is the function I want to invoke.
        $code = { 
            # Update 1, added parameter
            param($cb)
            $cb.Scan($PrepareFileName, $NailDirName, $HtmlFileName) 
        }
        # Create a runspace
        $runspace = [runspacefactory]::CreateRunspace()
        # Update 1, inject parameter
        $newThread = [PowerShell]::Create().AddScript($code).AddParameter(‘cb’,$callback)
    
        # Add the runspace
        $newThread.Runspace = $runspace
        $runspace.Open()
        $handleTh = $newThread.BeginInvoke()
        $nTimes = 0;
        do
        {
            $nTimes++;
            if($handleTh.IsCompleted -or $nTimes -gt 10)
            {
              break;  
            }
            Start-Sleep -Milliseconds 500
    
        } while($true)
    
        $newThread.EndInvoke($handleTh)
        $newThread.Dispose()
    }
    catch{
    }
    

    Hope that helps.

    enter image description here