views:

260

answers:

2

I am writing a VB.NET program and I'm trying to accomplish the following:

  • Read and loop through a text file line by line
  • Show the event of the loop on a textbox or label until a button is pressed
  • The loop will then stop on any number that happened to be at the loop event and
  • When a button is pressed again the loop will continue.

Code

Imports System.IO    
Public Class Form1


'Dim nFileNum As Integer = FreeFile() ' Get a free file number
Dim strFileName As String = "C:\scb.txt"
Dim objFilename As FileStream = New FileStream(strFileName, _
    FileMode.Open, FileAccess.Read, FileShare.Read)
Dim objFileRead As StreamReader = New StreamReader(objFilename)
'Dim lLineCount As Long
'Dim sNextLine As String


Private Sub btStart_Click(ByVal sender As System.Object, _ 
                          ByVal e As System.EventArgs) _
     Handles btStart.Click

    Try
        If objFileRead.ReadLine = Nothing Then

            MsgBox("No Accounts Available to show!", _
               MsgBoxStyle.Information, _
               MsgBoxStyle.DefaultButton2 = MsgBoxStyle.OkOnly)
            Return
        Else

            Do While (objFileRead.Peek() > -1)

            Loop
            lblAccounts.Text = objFileRead.ReadLine()

            'objFileRead.Close()
            'objFilename.Close()
        End If

    Catch ex As Exception
        MessageBox.Show(ex.Message)
    Finally
        'objFileRead.Close()
        'objFilename.Close()
    End Try


End Sub

Private Sub Form1_Load(ByVal sender As System.Object, _ 
                       ByVal e As System.EventArgs) _
  Handles MyBase.Load

End Sub
End Class

Problem

I'm able to read the text file but my label will only loop if I hit the start button. It goes to the next line, but I want it to continue to loop through the entire file until I hit a button telling it to stop.

A: 

I can tell you one thing, this:

lblAccounts.Text = objFileRead.ReadLine()

has to be inside the Do While loop:

Do While (objFileRead.Peek() > -1)
    lblAccounts.Text = objFileRead.ReadLine()
Loop

Edited to add

The above code isn't actually useful. The text file will be read so fast that only the last line will show in lblAccounts.

You can at least see the names fly by if you do this:

Do While (objFileRead.Peek() > -1)
    lblAccounts.Text = objFileRead.ReadLine()
    lblAccounts.Update()
    Application.DoEvents()
Loop

This should give you a clue about stopping and starting. Here's pseudocode:

dim Runnning as boolean = false ' global
sub button_handler()
    if Running then
        Running = false
    else
        Running = true
        KeepReading()
    end if
end sub

sub KeepReading()
    Do While (objFileRead.Peek() > -1 and Running)
        lblAccounts.Text = objFileRead.ReadLine()
        lblAccounts.Update()

        ' this will let the screen update, also let button
        ' messages through:
        Application.DoEvents() 
    Loop
    if running then
        MsgBox("Done!")
        Running = false
    end if
end sub
egrunin
I wouldn't read from the file directly in such a (fast) loop, I'd cache it.
Bobby
@egrunin i ve tried yours bt not showing any thing from my label
Ousman
ok @egrunin let me try dis
Ousman
hi the Application.DoEvents() and the Update() have helps me a lot i have use a Application.threading to reduce the milliseconds my loop will show and its ok. But how to stop the loop and i dont want the loop to stop when it reaches at the end of the file i want it to begin from the start again. it should only stop when i press a button or a keypress. tanks
Ousman
A: 

You should use a Background-Worker for this kind of Job, also I wouldn't read form the file directly, I'd cache it.

Imports System.IO

' --> Private Declaration in the Form '
Private _path As String = "YourPathHere"
Private _lines() As String = File.ReadAllLines(Me._path)
Private _lineCounter As Integer = 0
Private _loop As Boolean = True

' --> BackgroundWorker-DoWork-Event '
While Me._loop
    Me._lineCounter += 1
    If Me_linceCounter >= Me._lines.Length Then Me._lineCounter = 0
    Me.BackgroundWorker.ReportProgress(0)
End While

' --> BackgroundWorker-ProgressChanged-Event '
Me.YourTextBoxHere.Text = Me._lines(_lineCounter)

' --> Button-Click-Event '
If Me._loop Then
    Me._loop = False
Else
    Me._loop = True
    Me.BackgroundWorker.RunWorkerAsync()
End If

Edit:

  Private Sub BGW_DoWork(ByVal sender As Object, _
                         ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker.DoWork
        While Me._loop
              Me._lineCounter += 1
              If Me_linceCounter >= Me._lines.Length Then Me._lineCounter = 0
              Me.BackgroundWorker.ReportProgress(0)
        End While
  End Sub

Same goes for the ProgressChanged-Event.

Edit2: And don't forget to set the property WorkerReportsProgress to True.

Bobby
OK TANKS LET ME TRY IT @BOBBY
Ousman
@Boddy i got the following error message'Public Event DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)' is an event, and cannot be called directly. Use a 'RaiseEvent' statement to raise an event. sorry but i still cant get it
Ousman
@Ousman: It is an event, so you need to handle it accordingly, like you'd handle a Click-Event of a Button. See my Edit.
Bobby
hi i still dont know where to find the event for ReportProgress-Event
Ousman
@Ousman: Oh sorry, the associated function is called `ReportProgress`, but the event is called `ProgressChanged`.
Bobby
yes but dis code is my problem Me.BackgroundWorker1.DoWork(). I still have an error if i used your code.
Ousman
@Ousman: Sorry, I really should start looking up those things...it's `RunWorkerASync()`.
Bobby