4

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{

}
8
  • Where are beginning the new thread? Commented May 8, 2019 at 1:37
  • Isn't that the sentence? $handleTh = $newThread.BeginInvoke() @RossBush Commented May 8, 2019 at 2:41
  • New PowerShell's Runspace that you created known nothing about variables in your current Runspace. Commented May 8, 2019 at 3:39
  • I think you're right. Is there any good way for the new PowerShell to take variables from the parent's runtime? @PetSerAl Commented May 8, 2019 at 6:29
  • @不知火舞 Try using PosshRSJob, it lets you handle powershell jobs in different run spaces and can let you access variables from the "parent scope". github.com/proxb/PoshRSJob Commented May 8, 2019 at 7:23

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

13 Comments

Thank you for your answer. I'm doing the same now. But the same result: $handleTh. IsCompleted always equals $true. @Moerwald
It means that the result of $handleTh.IsCompleted is $true before it has entering the Scan function. @Moerwald
I've done a test. I replace $cb.Scan($PrepareFileName, $NailDirName, $HtmlFileName) with Start-Sleep -Seconds 30. During the sleep time $handleTh.IsCompleted was false. Could it be that $cb is $null or the Scan method return with an error?
Replace $cb.Scan($PrepareFileName, $NailDirName, $HtmlFileName) with Start-Sleep -Seconds 30. Is $handleTh now false ?
That's my question. There's no problem executing cmdlet, but executing functions won't work. It's perfectly okay to run this function without executing it through [PowerShell]:: Create ().
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.