Winforms 为什么我的WindowsForm在执行循环时没有响应

Winforms 为什么我的WindowsForm在执行循环时没有响应,winforms,powershell,Winforms,Powershell,这可能是一个很难回答的问题。我编写了一个脚本来检查进程的响应属性。为了可视化脚本正在运行,我创建了一个windows窗体,您可以在其中查看监视的进程。脚本运行得很好,但我无法使用winform执行任何操作。无法最小化或关闭它,当我将光标移动到windowsform时,我的鼠标光标将切换到沙漏符号。你知道为什么吗 当我注释掉while循环时,winform也没有响应 这是我的密码: if ($ShowWindowsForm){ $window = New-Object System.Win

这可能是一个很难回答的问题。我编写了一个脚本来检查进程的响应属性。为了可视化脚本正在运行,我创建了一个windows窗体,您可以在其中查看监视的进程。脚本运行得很好,但我无法使用winform执行任何操作。无法最小化或关闭它,当我将光标移动到windowsform时,我的鼠标光标将切换到沙漏符号。你知道为什么吗

当我注释掉while循环时,winform也没有响应

这是我的密码:

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
}

如果有人遇到和我一样的问题,我现在得到了答案

首先,如果您只是创建一个GUI并进行一些处理,那么它们使用相同的线程。例如:

# 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 }
由于使用了
.ShowDialog()
方法,PowerShell现在将显示
$window
,但Windows窗体(
$window
)将不会响应。这是因为您在显示Windows窗体对话框的同一线程中运行循环

因此,我们需要为循环创建一个后台任务,这样它自己就有一个线程。这就是PowerShell的
Start Job
cmdlet的用途

假设您正在监视一个进程,并希望在Windows窗体中可视化它。您的代码如下所示:

$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()
$target=“firefox”
#工作
开始作业-参数列表$target{
参数(目标)
while((获取进程$target).Responding){Sleep-millides 100}
if(!(获取进程$target).Responding{}
}
#窗口窗体
$window=新对象System.Windows.Forms.Form
$window.text=“流程观察者”
$window.size=新对象系统.Drawing.size(350100)
$window.location=新对象系统.图纸.尺寸(100100)
$window.ShowDialog()
有了这段代码,您的Windows窗体负责,您的循环在后台执行。我还想通过这个代码示例说明的是,必须使用
-argumentlist
参数和
param()
语句将在作业脚本块之外声明的变量传递给作业。否则就不行了


我希望这个答案能帮助一些人,因为谷歌并没有给出一个好的答案(或者我只是没有找到一个好的答案)

thx,将我的问题标记为简单的答案,实际上:在一个线程上一次只能发生一件事。您正在UI线程上运行一个循环,这会阻止任何UI内容同时发生。这意味着您的应用程序变得愚蠢(无响应)。解决方案是在后台线程上完成所有处理。不确定Powershell是否内置了类似的功能。如果没有,那么您应该使用为GUI编程而设计的语言,如C#或VB.NET。请注意,链接的问题可能是重复的,但答案是可怕的建议。