1

I'm writing a simple checksum generator app using C# for large files. It's working quite fine, but users would like to see some sort of progress bar since the app freezes for a a few dozen seconds.

Here is a a sample of code I use (BufferedStream increased a lot the app performance):

private static string GetSHA5(string file)
{
    using (var stream = new BufferedStream(File.OpenRead(file), 1200000))
    {
        var sha5 = new SHA512Managed();
        byte[] checksum_sha5 = sha5.ComputeHash(stream);
        return BitConverter.ToString(checksum_sha5).Replace("-", String.Empty);
    }
}

My question is, is it possible to get the buffer "progress" ? Because I guess internally it operates some sort of division and looping.

May.D
  • 1,832
  • 1
  • 18
  • 34
  • Do you want to know the progress of the hash calculation or the progress of the buffer loading? – Pretasoc Jan 07 '19 at 17:20
  • 1
    I suppose you could create a custom stream descendant and pass in, which acts as an adapter, reporting progress as it reads from the underlying stream on behalf of SHA. – 500 - Internal Server Error Jan 07 '19 at 17:22
  • 1
    You could add a timer and then divided the stream position by the stream length. The SHA is reading in blocks. See source : https://referencesource.microsoft.com/#mscorlib/system/security/cryptography/sha512managed.cs,63c7993869a0e17a – jdweng Jan 07 '19 at 17:25
  • I want to know the progress of hash calculation. @500-InternalServerError you mean creating a custom class that inherit BufferedStream ? I'm not sure to understand your solution. – May.D Jan 07 '19 at 17:47
  • @jdweng It could be a good solution though I don't know how to get the stream position and include it in my code. – May.D Jan 07 '19 at 17:48
  • Position is a property of the Stream. Declare the variable "stream" outside the private method so the timer event has access to the variable. – jdweng Jan 07 '19 at 21:24
  • "since the app freezes for a a few dozen seconds" *Don't do that*. It sounds like you're blocking the UI thread. Don't block the UI thread. Do the processing in a background thread. – Servy Jan 08 '19 at 14:38
  • Yes indeed, I solved the problem with the solution I posted below. – May.D Jan 08 '19 at 14:39
  • I disagree with the duplicate flag though, since the question was about BufferedStream, I wanted another implementation than the one I ended up using. – May.D Jan 08 '19 at 14:41

1 Answers1

1

I tried implementing jdweng solution but I had trouble accessing threads to update my progress bar with the position variable. In the end I rewrote my code using background_worker and a custom buffer. Here is a sample of a it.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    dynamic data = e.Argument;
    string fPath = data["file"];
    byte[] buffer;
    int bytesRead;
    long size;
    long totalBytesRead = 0;
    using (Stream file = File.OpenRead(fPath))
    {
        size = file.Length;
        progressBar1.Visible = true;
        HashAlgorithm hasher = MD5.Create();
        do
        {
            buffer = new byte[4096];
            bytesRead = file.Read(buffer, 0, buffer.Length);
            totalBytesRead += bytesRead;
            hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
            backgroundWorker1.ReportProgress((int)((double)totalBytesRead / size * 100));
        }
        while ( bytesRead != 0) ;

        hasher.TransformFinalBlock(buffer, 0, 0);
        e.Result = MakeHashString(hasher.Hash);

    }

}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}
  private void md5HashBtn_Click(object sender, EventArgs e)
        {
            if (MD5TextBox.Text.Length > 0)
            {
                Dictionary<string, string> param = new Dictionary<string, string>();
                param.Add("algo", "MD5");
                param.Add("file", MD5TextBox.Text);
                backgroundWorker1.RunWorkerAsync(param);
            }
        }
May.D
  • 1,832
  • 1
  • 18
  • 34