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