【问题标题】:process.start freezing my application(VS 2013)process.start 冻结我的应用程序(VS 2013)
【发布时间】:2013-10-13 14:27:04
【问题描述】:

所以我正在尝试制作一个启动 3rd 方 exe 来执行一些文件操作的应用程序, 基于文件名列表。 因此,如果列表有 13 个项目,我将循环 13 次,每次启动外部进程,通知用户现在正在处理哪个文件,启动进程并等待它退出。为了通知用户,另一个列表框用作喊话框。问题是, .waitforexit() 以某种奇怪的方式冻结了整个线程,因此外部程序被正常调用,文件被正常处理,但主窗口被冻结,直到所有项目都完成。所以基本上 Shoutbox 被冻结并且只有在整个循环完成后才会收到所有信息的垃圾邮件。我尝试了很多方法来实现这一点,例如启动新线程、使用线程池、计时器等等。任何帮助表示赞赏。 代码:

Imports System.Windows.Threading
Imports System.Windows.Forms
Imports System.IO
Imports System.Threading        

If Listbox2.Items.Count > 0 Then
            tabctrl.SelectedIndex = 2
            Listbox3.Items.Add(DateTime.Now.ToString & ": Process initiated.")
            For i = 0 To Listbox2.Items.Count - 1
                Listbox3.Items.Add(DateTime.Now.ToString & ": Processing :" & Listbox1.Items.Item(i))
                If System.IO.File.Exists(Listbox2.Items.Item(i)) = False Then
                    Dim pInfo As New ProcessStartInfo()
                    With pInfo
                        .WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden
                        .FileName = System.IO.Directory.GetCurrentDirectory & "\" & "myapp.exe"
                        .argouments = "w/e"
                    End With
                    Dim p As Process = Process.Start(pInfo)
                    p.WaitForExit()
                    p.Dispose()
                Else
                    Listbox3.Items.Add(DateTime.Now.ToString & ":! " & Listbox2.Items.Item(i) & " already exists. Moving to next file..")
                End If
            Next
            Listbox3.Items.Add("*-*")
            Listbox3.Items.Add(DateTime.Now.ToString & ": Done.")
        End If

【问题讨论】:

  • WaitForExit 阻塞线程。但在进程之后/之前,您可以添加Application.DoEvents(),以便主线程处理其事件。
  • 如果一旦你启动 Application.DoEvents 路径,它将永远主宰你的命运,吞噬你,它将...
  • 因为我忘了提到这是 WPF Application.DoEvents() 至少用这种语法是不可能的..

标签: vb.net process waitforexit


【解决方案1】:

问题是您(至少在您发布的代码中)正在 UI 线程上调用 WaitForExit()。 UI 线程负责重绘窗口,因此如果您阻止它,例如通过调用 WaitForExit(),它不会重绘 ui,并且应用程序似乎被冻结了。

你需要做的是在另一个线程或线程池上调用它,我推荐使用Tasks

Task.Run( Sub()
  Dim p As Process = Process.Start(pInfo)
  p.WaitForExit()
End Sub)

但是,由于您没有对Process.Start() 调用的结果进行任何操作,因此您也可以考虑根本不调用WaitForExit()

由于您使用的是 VS2013,您也可以使用await operator 等待进程完成:

await Task.Run( Sub()
  Dim p As Process = Process.Start(pInfo)
  p.WaitForExit()
End Sub)

请注意,您还必须将 async 关键字添加到周围的方法中

【讨论】:

  • Await方法居然解决了问题!!!我必须将 Async 添加到按钮单击处理程序,以及您发布的等待代码以达到预期的效果。谢谢。
  • 太棒了 :) 我应该提到这一点,我会编辑回复以供将来参考
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多