Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
525 views
in Technique[技术] by (71.8m points)

winforms - Why is my WindowsForm not responding while executing loop

This may be a question that is difficult to answer. I wrote a Script that checks the responding property of a process. to visualize that the script is running, i created a windows form where you can see which process is watched. The script runs perfectly, but I can't do anything with my winform. Can't minimize or close it, my mouse cursor switches to the hourglass symbol as soon as I move the cursor to the windowsform. any ideas why?

The winform is also not responding when I comment out the while loop

here's my code:

if ($ShowWindowsForm){
    $window = New-Object System.Windows.Forms.Form
    $window.text = "Process Watcher"
    $window.size = New-Object System.Drawing.Size(350,100) 
    $window.location = New-Object System.Drawing.Size(100,100) 
    $icon = [system.drawing.icon]::ExtractAssociatedIcon($PSHOME + "powershell.exe")
    $window.Icon = $Icon
    $text = New-Object System.Windows.Forms.Label
    $text.Text = "Folgender Prozess wird überwacht:`n$target.exe"
    $text.location = New-Object System.Drawing.Size(10,10) 
    $text.AutoSize = $true
    $window.Controls.Add($text)
    $window.Show()
}
while (1) {
    sleep -Milliseconds 100
    if(!((get-process $target).Responding -eq $true)) {
    #do stuff
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I got the answer now, if anyone runs into the same problem as I have.

First of all, if you just create a GUI and do some processing, they use the same thread. example:

# Windows Form    
$window = New-Object System.Windows.Forms.Form
$window.text = "Process Watcher"
$window.size = New-Object System.Drawing.Size(350,100) 
$window.location = New-Object System.Drawing.Size(100,100) 
$window.ShowDialog()

# Processing
while (1) { # Do Stuff }

PowerShell will now show the $window because of the .ShowDialog() method, but the Windows Form ($window) won't be responsive. That's because you're running a loop in the same thread as you show the Windows-Form Dialog.

So we need to create a Background Task for the loop, so it has a thread for itself. That's what PowerShell's Start-Job cmdlet is for.

let's say you're monitoring a process, and want to visualize it in a Windows-Form. Your Code will look like this:

$target = "firefox"

# Job
Start-Job -argumentlist $target {
    param($target)
    while ((get-process $target).Responding) {Sleep -Milliseconds 100}
    if (!(get-process $target).Responding) {<# Do Stuff #>}
}

# Windows Form    
$window = New-Object System.Windows.Forms.Form
$window.text = "Process Watcher"
$window.size = New-Object System.Drawing.Size(350,100) 
$window.location = New-Object System.Drawing.Size(100,100) 
$window.ShowDialog()

with this code, your Windows-Form is responsible, and your loop is executing in the background. What i also want to show with this code example is, that you have to pass a variable which you declared outside the job scriptblock to the job with the -argumentlist Parameter and param() statement. otherwise it won't work.

I hope this answer will help someone because google doesn't really give a good answer to this (or I just didn't find a good one)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...