Question:
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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.") |
Answer:
Noticed a couple of mistakes in your script. Firstly $thread_job, try this instead:
1 2 |
[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:
1 2 |
$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