?
Solved

program hangs while batch file is running

Posted on 2006-05-24
4
Medium Priority
?
201 Views
Last Modified: 2010-07-27
Hi,
  When one of the buttons in my program is clicked, it creates a batch file & 2 SQL scripts. It then runs the batch file which runs the 2 SQL scripts which output 2 text files. The text files are then parsed for the data required.
The problem is that when the batch file is running (about 20 seconds) the program & progress form freeze.The skin comes off the form also. Once the batch file finishes the form refresh's itself & the program is fine.
I thought the batch file would run independently of the program & the program would just check to see if it had finished once a second.
Does anyone know how I can get around this so that the forms don't freeze.

      ''' RUN MULTI.BAT
        Dim s As New System.Diagnostics.Process
        s.StartInfo.FileName = Application.StartupPath & "\temp\" & LOT & "MULTI.bat"
        s.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
        s.Start()
        's.WaitForExit(30000)
        i = 0
        Do Until i = 30
            If s.HasExited = False Then
                PROGRESS.ProgressBar1.Value = PROG
                PROGRESS.Refresh()
                frm.Refresh()

                System.Threading.Thread.Sleep(1000)
            Else
                PROG = 32
                PROGRESS.ProgressBar1.Value = PROG
                PROGRESS.Refresh()
                Exit Do
            End If
            i = i + 1
            PROG = PROG + 1
        Loop
        s.Close()
 
Thanks for the help,
E_MURF1.
0
Comment
Question by:e_murf1
  • 2
4 Comments
 
LVL 12

Expert Comment

by:gbzhhu
ID: 16754603
Use threads

System.Threading.Thread class
0
 
LVL 12

Expert Comment

by:gbzhhu
ID: 16754618
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 2000 total points
ID: 16755265
If you want to hold in a loop that won't lock up the GUI then:

            While Not s.HasExited
                System.Threading.Thread.Sleep(50)
                Application.DoEvents()
            Wend

Otherwise here is a threaded implementation that encapsulates the thread in a class:

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents Label2 As System.Windows.Forms.Label
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.Label1 = New System.Windows.Forms.Label
        Me.Label2 = New System.Windows.Forms.Label
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(40, 40)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(104, 24)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(8, 120)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(272, 24)
        Me.Label1.TabIndex = 1
        Me.Label1.Text = "Label1"
        '
        'Label2
        '
        Me.Label2.Location = New System.Drawing.Point(8, 152)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(272, 24)
        Me.Label2.TabIndex = 2
        Me.Label2.Text = "Label2"
        '
        'Form2
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form2"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Public Delegate Sub StatusUpdate(ByVal sender As MyProcess, ByVal info As MyProcess.ProcessInfo)

    Private myThreads As New ArrayList

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim mp As New MyProcess("calc")
        AddHandler mp.ProcessUpdate, AddressOf Me.ProcessUpdate
        myThreads.Add(mp)
        mp.StartProcess()
    End Sub

    Private Sub ProcessUpdate(ByVal sender As MyProcess, ByVal info As MyProcess.ProcessInfo)
        ' If necessary, prevent cross-thread UI update violations via Delegates
        If Me.InvokeRequired Then
            Dim su As New StatusUpdate(AddressOf Me.UpdateGUI)
            Me.Invoke(su, New Object() {sender, info})
        Else
            UpdateGUI(sender, info)
        End If
    End Sub

    Private Sub UpdateGUI(ByVal sender As MyProcess, ByVal info As MyProcess.ProcessInfo)
        ' do something with the data in here...
        ' (it is safe to update the GUI since a Delegate was used if necessary)

        ' some possibilities...
        Select Case info.Status
            Case MyProcess.ProcessStatus.Complete
                Select Case info.ExeName
                    Case "calc"
                        Label1.Text = info.ExeName
                        Label2.Text = info.Message

                    Case "c:\prog1.exe"
                        ' take next step...

                End Select

            Case MyProcess.ProcessStatus.Aborted
                ' do something else in here..

            Case MyProcess.ProcessStatus.Failed
                ' or something else in here...

        End Select
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        Dim mp As MyProcess
        For Each mp In myThreads
            mp.StopProcess()
        Next
    End Sub

    Public Class MyProcess

        Public Enum ProcessStatus
            Complete
            Aborted
            Failed
        End Enum

        Public Structure ProcessInfo
            Public ExeName As String
            Public Status As MyProcess.ProcessStatus
            Public Message As String

            Public Sub New(ByVal ExeName As String, ByVal Status As ProcessStatus, ByVal Message As String)
                Me.ExeName = ExeName
                Me.Status = Status
                Me.Message = Message
            End Sub
        End Structure

        Public Event ProcessUpdate(ByVal sender As MyProcess, ByVal info As MyProcess.ProcessInfo)

        Private Exe As String
        Private t As System.Threading.Thread
        Private p As Process
        Private abort As Boolean = False

        Public ReadOnly Property ExeName() As String
            Get
                Return Exe
            End Get
        End Property

        Public ReadOnly Property ExeComplete() As Boolean
            Get
                If Not IsNothing(p) Then
                    Return p.HasExited
                Else
                    Return False
                End If
            End Get
        End Property

        Private Sub New()
        End Sub

        Public Sub New(ByVal fullPathToExe As String)
            Exe = fullPathToExe
        End Sub

        Public Sub StartProcess()
            If IsNothing(p) Then
                t = New System.Threading.Thread(AddressOf Me.MonitorExe)
                t.Start()
            End If
        End Sub

        Private Sub MonitorExe()
            Try
                p = Process.Start(Exe)
                While Not abort AndAlso Not p.HasExited
                    p.WaitForExit(250)
                End While
                If Not abort Then
                    RaiseEvent ProcessUpdate(Me, New ProcessInfo(Exe, ProcessStatus.Complete, "Complete"))
                Else
                    p.Kill()
                    RaiseEvent ProcessUpdate(Me, New ProcessInfo(Exe, ProcessStatus.Aborted, "Aborted"))
                End If
            Catch ex As Exception
                RaiseEvent ProcessUpdate(Me, New ProcessInfo(Exe, ProcessStatus.Failed, ex.Message))
            End Try
        End Sub

        Public Sub StopProcess()
            abort = True
        End Sub

    End Class

End Class
0
 

Author Comment

by:e_murf1
ID: 16755898
Hi gbzhhu,
  I tried using the different threads & the program still froze, I could have been doing it wrong.

Hi Idlemind,
  I used your while loop & it worked perfect. I think mine wasn't working because I didn't use 'Application.DoEvents()'. I thought that having Refresh() in my loops would keep the GUI updated. I just have to go find out what 'DoEvents' is actually doing.

Thanks for your help, much appreciated.  
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
A while ago, I was working on a Windows Forms application and I needed a special label control with reflection (glass) effect to show some titles in a stylish way. I've always enjoyed working with graphics, but it's never too clever to re-invent …
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question