ProgressBar Dilemma

My user wishes to see visual proof that their app is processing files. I've never used a ProgressBar before and I'm trying to get a test to work before I 'muddy-up' my production app.
I've gotten to the point that I can get the Value to display as each record in a file is read; however, when it gets to the final record it displays the following exception:

Value of '1894' is not valid for 'Value'. 'Value' should be between 'minimum' and 'maximum'.
Parameter name: Value

I know what the problem is (there's 1893 records in my test file), I just don't know how to fix it. I've tried to set the record count to it's value +1 (this.thisProgressBar.Maximum = Convert.ToInt32 ( m_strInputFile.Length / 1024 + 1 ); ), but still get the same exception.

Any assistance on this would really be appreciated.

private void OpenInputFile ( )

{

string strInText="";

OpenFileDialog dlgOpenFile = new OpenFileDialog ( );

dlgOpenFile.InitialDirectory = m_strInitDir;

dlgOpenFile.Filter = m_strInitFileFilter;

dlgOpenFile.FilterIndex = 1;

dlgOpenFile.RestoreDirectory = true;

if ( dlgOpenFile.ShowDialog ( ) == DialogResult.Cancel )

{

this.buttonStartDisplay.Enabled = true;

dlgOpenFile.Dispose ( );

}

else

{

m_strInFilePath = dlgOpenFile.FileName;

FileInfo m_strInputFile = new FileInfo ( m_strInFilePath );

sr_FileReader = m_strInputFile.OpenText ( );

this.thisProgressBar.Maximum = Convert.ToInt32 ( m_strInputFile.Length / 1024 );

try

{

using ( sr_FileReader )

{

while ( ( strInText = sr_FileReader.ReadLine ( ) ) != null )

{

this.thisProgressBar.Value += 1;

}

}

}

catch ( Exception ex )

{

MessageBox.Show ( "An exception has occured while\n " +

"pre-processing this file. \n\n" +

ex.Message + "\n\n",

"Exception Error",

MessageBoxButtons.OK );

}

}

}




Answer this question

ProgressBar Dilemma

  • Bobbias

    Yeah, with such large files it seems like it would be best to just update based on the number of kilobytes read. If the records are all about the same size, it will work similarly to going based on the number of lines. The potential problem would be that if a single record was half of the file size, then the progress bar would jump after processing that record.

    Generally though, there is no reason to have progress bars be perfect, as they usually just serve as a visual representation that the process is running and of how much time is left.

  • Cesar Francisco

    Also, try calling your OpenFileDialog with using statement, which will take care of proper disposing for you, like in this example:

    using ( OpenFileDialog dlgOpenFile = new OpenFileDialog ( ))

    {

    dlgOpenFile.InitialDirectory = m_strInitDir;

    dlgOpenFile.Filter = m_strInitFileFilter;

    dlgOpenFile.FilterIndex = 1;

    dlgOpenFile.RestoreDirectory = true;

    if ( dlgOpenFile.ShowDialog ( ) == DialogResult.Cancel )

    {

    this.buttonStartDisplay.Enabled = true;

    return;

    }

    m_strInFilePath = dlgOpenFile.FileName;

    ...

    }



  • Niku

    It's difficult to determine the number of lines, contained in a file, without reading it through... So, if we're not talking *very* large files, you can read the whole content of a file at once and create a line array:

    string[] lines = File.ReadAllLines(path);
    int recordCount = lines.Length;

    Then, instead of seeking through file stream, run through string array and increment the progress bar. Remember, doing this, you're reading the whole file into the memory, so processing large files might not work as expected...

    Andrej



  • Rand AlThor

    Ok, then when I thought I was getting the file record count I wasn't (never was good at math). So, how does one retrieve the actual file record count from the file , or is this possible

  • A W Garland Sr

    So in other words, ProgressBars and other visual controls similar to it are there to give users the "warm-fuzzies". I always used a Label and displayed a running count that was updated as the lines were read; always worked for me.

    Rhubarb



  • White-Tiger-Eyes

    Well, the smaller of the files just took about 3 minutes to load into Notepad with 1,501,203 lines. To me, I don't think my user's would accept that. Now, If I load the file twice just to get a line count, that may pose a situation.

    Rhubarb



  • aanersiieaaoa

    Rhubarb wrote:
    ... from 300,000 to 900,000 KB...

    Doesn't sound like too much. But then again, that depends on the system on which the application is running. You can try reading files into memory anyway and see how the system behaves...

    Andrej



  • JoeCodester

    Ok, I see the roadblock now. I'm coming from Mainframe-speak. Files are made up of individual records, to me, a record is a line of characters that ends with a carriage return/line-feed. What I need to retrieve is the count of each line in a file.

  • kaborka

    Ok, thanks Andrej. Unfortunatly, several of the files I read/process are extremely large (from 300,000 to 900,000 KB). It looks like I may just have to display a 'relative' progress. But then, there's the problem of setting a valid Maximum value. Too low and it'll pass an exception. Ahhh, C# is so much fun!

    Greg
    'Rhubarb'



  • Rtalan

    These files are huge. I tried to perform a simple Open/Read on one, no data processing involved and it took about 5 minutes just to read the file!

    Never had the pleasure of a Vista experience. I don't think my office will go that route, we were still using Windows 98 up until 2003 when we finally moved to XP!

    Rhubarb



  • chris441962

    As I'm seeing it, you're calculating your Max value by converting your file's length into kilobytes, but you're reading the file line by line. This would work only in case when each line is exactly 1 kb in length (including new line characters)...

    I'm not sure what a "record" in your case is, but if it is a line then you'll have to find out the number of lines before you start processing the file.

    For a quick and dirty workaround, you can start with something like in this piece of code and see what's happening:

    while ( ( strInText = sr_FileReader.ReadLine ( ) ) != null )

    {
        int record = this.thisProgressBar.Value += 1;

        if (record > this.thisProgressBar.Maximum)

        {

            record = this.thisProgressBar.Maximum;

        }

        this.thisProgressBar.Value = record;
    }

    Andrej



  • Michael Hansen

    The problem is that you are setting the progress bar maximum based on the number of kilobytes in the file (since FileInfo.Length is in bytes). So the units of the progress bar Value property should then be in kilobytes. However, after reading every line you are incrementing the value by 1, which means 1KB in this context.

    You should replace this.thisProgressBar.Value += 1; with this.thisProgressBar.Value = sr_FileReader.BaseStream.Position / 1024;

    Also, after you get it working normally you should manually check whether the new value will be greater than the max, and if so set it to the 100% value.

  • Haojun

    Andrej Tozon wrote:

    Rhubarb wrote:
    ... from 300,000 to 900,000 KB...

    Doesn't sound like too much.

    I obviously misread the number... So you're working with 900 Megs text files Not bad :) And yes, reading all this at once is out of the question...

    And talking about the warm-fuzzies... have you seen how progress bar looks in Vista

    Andrej



  • domochan

    I'm still not sure what the record is in your case. Is it a line If it's fixed length record, you can just calculate the number of records - fileLength / recordLength.

    Andrej



  • ProgressBar Dilemma