Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell thread handling problem

I have a powershell problem, and maybe someone can help me. I'm using powershell 2.0, and i want to create, and use threads. I know that i can use jobs, but that is not what i want. I want a script, that creates windows forms, and runs background threads too. Since forms needs STA, this is not easy. Running "powershell.exe -sta" is not a solution.

Below is my script that I wrote, for simple thread handling. But it doesn't work. Even the new thread wont be created. Any suggestion, what is wrong? Please help me if you can!

Regards, Peter.

function ThreadProc() {
    for ($i = 0; $i -lt 10; $i++) {
        $ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
        Write-Host "ThreadProc ($ApartmentState): $i"
        # Yield the rest of the time slice.
        [System.Threading.Thread]::Sleep(0)
    }
}

$ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
Write-Host "Main thread ($ApartmentState): Start a second thread."

$thread_job = New-Object System.Threading.ThreadStart(ThreadProc)
$thread = New-Object System.Threading.Thread($thread_job)
$thread.CurrentThread.SetApartmentState([System.Threading.ApartmentState]::STA)
$thread.Start()

for ($i = 0; $i -lt 4; $i++) {
    Write-Host("Main thread: Do some work.")
    [System.Threading.Thread]::Sleep(0)
}

Write-Host("Main thread: Call Join(), to wait until ThreadProc ends.")
$thread.Join()
Write-Host("Main thread: ThreadProc.Join has returned. Program end.")
like image 822
Peter Kiraly Avatar asked Sep 09 '11 06:09

Peter Kiraly


2 Answers

Noticed a couple of mistakes in your script. Firstly $thread_job, try this instead:

[System.Threading.ThreadStart]$thread_job = {ThreadProc};

You need to put the brackets around ThreadProc or it will be evaluated rather than passed as a function. Secondly you can just specify the type for delegates like ThreadStart and PowerShell will convert things for you; no need for New-Object.

Secondly CurrentThread is a static member - I'm guessing $thread.CurrentThread is a typo and you meant:

$thread.SetApartmentState([System.Threading.ApartmentState]::STA);

I imagine you'll still have problems getting it to work though - whenever I've tried using threads in PowerShell before I've always had nasty crashes with no real explanation...

Can you write a cmdlet in C# and call into that instead? Might be easier to do things that way - you could setup a new Runspace and run your command in the other Runspace's thread.

EDIT

Found these links that might help you:

http://weblogs.asp.net/adweigert/archive/2008/04/29/powershell-threading-for-powershell-v1-0.aspx http://blogs.msdn.com/b/powershell/archive/2007/03/23/thread-apartmentstate-and-powershell-execution-thread.aspx

like image 161
MrKWatkins Avatar answered Oct 11 '22 22:10

MrKWatkins


I think that your question is somewhere close to a post called Powershell and Backgroundworker.Background worker is for running .NET code on a background thread.

Powershell, though is working on the top of .NET doesn't produce intermediate language (IL). Its an interpreted language and its code cannot run outside of the context of a powershell runspace. you perhaps can use your code creating our own PowerShell Runspace and running your script there, and marshall the results back to your primary session.

like image 31
JPBlanc Avatar answered Oct 11 '22 22:10

JPBlanc