2014-02-17 49 views
1

我想要計算一個文件的MD5散列,並把它放在一個文本框中,我也有一個ProgressBar應該保持運行,而散列如果被計算,我將ProgressBar設置爲字幕,將在我選擇一個文件時運行,但只要散列計算開始,條形圖凍結直至完成。 這是我的代碼:C#ProgressBar凍結

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Drawing; 
using System.IO; 
using System.Linq; 
using System.Security.Cryptography; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 


namespace Calcula_MD5_BAR 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Stopwatch timer = new Stopwatch(); 
      var openFileDialog1 = new OpenFileDialog(); 
      progressBar1.Style = ProgressBarStyle.Marquee; 
      progressBar1.MarqueeAnimationSpeed = 30; 
      if (openFileDialog1.ShowDialog() == DialogResult.OK) 
      {  
       timer.Start(); 
       textBox1.Text = GetFileMD5Hash(openFileDialog1.FileName); 
       timer.Stop(); 
       lblTime.Text = timer.Elapsed.ToString(); 
       progressBar1.Style = ProgressBarStyle.Continuous; 
       progressBar1.Increment(100); 
      } 
      progressBar1.MarqueeAnimationSpeed = 0; 
     } 

     protected string GetFileMD5Hash(string nomeArquivo) 
     { 
      FileStream file = new FileStream(nomeArquivo, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
      MD5 md5 = new MD5CryptoServiceProvider(); 
      byte[] retVal = md5.ComputeHash(file); 
      file.Close(); 

      StringBuilder sb = new StringBuilder(); 
      for (int i = 0; i < retVal.Length; i++) 
      { 
       sb.Append(retVal[i].ToString("x2")); 
      } 
      return sb.ToString(); 
     } 



    } 
} 
+0

這是完全正常的。進度條不能重繪,你的UI線程在樹林裏做別的事情,並沒有考慮UI線程的職責。您的用戶界面被完全凍結,它不會響應輸入並且不會重新繪製自己。使用BackgroundWorker來運行GetFileMD5Hash()方法。 –

+0

你的函數'GetFileMD5Hash(openFileDialog1.FileName)'阻塞了一個。您應該在另一個線程中運行它 – bansi

+0

您需要將密集工作移至單獨的線程,這樣UI線程可以自由管理UI。看看[BackgroundWorker](http://msdn.microsoft.com/en-us/library/cc221403(v = vs.95).aspx) – musefan

回答

3

你需要做你的非UI工作在非UI線程。 await與製作工作卸載到另一個線程和封送處理結果返回到UI線程的異步幫助很大容易的工作:

private async void button1_Click(object sender, EventArgs e) 
{ 
    Stopwatch timer = new Stopwatch(); 
    var openFileDialog1 = new OpenFileDialog(); 
    progressBar1.Style = ProgressBarStyle.Marquee; 
    progressBar1.MarqueeAnimationSpeed = 30; 
    if (openFileDialog1.ShowDialog() == DialogResult.OK) 
    {  
     timer.Start(); 
     textBox1.Text = await Task.Run(() => 
      GetFileMD5Hash(openFileDialog1.FileName)); 
     timer.Stop(); 
     lblTime.Text = timer.Elapsed.ToString(); 
     progressBar1.Style = ProgressBarStyle.Continuous; 
     progressBar1.Increment(100); 
    } 
    progressBar1.MarqueeAnimationSpeed = 0; 
} 
1

使用後臺工作者!完整的例子可以在這裏找到(粘貼下面!):

http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo

只需設置樣式爲選取框

public partial class Form1 : Form 
    { 
      public Form1() 
      { 
        InitializeComponent(); 
        Shown += new EventHandler(Form1_Shown); 

        // To report progress from the background worker we need to set this property 
        backgroundWorker1.WorkerReportsProgress = true; 
        // This event will be raised on the worker thread when the worker starts 
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
        // This event will be raised when we call ReportProgress 
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 
      } 
      void Form1_Shown(object sender, EventArgs e) 
      { 
        // Start the background worker 
        backgroundWorker1.RunWorkerAsync(); 
      } 
      // On worker thread so do our thing! 
      void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
      { 
        // Your background task goes here 
        for (int i = 0; i <= 100; i++) 
        { 
          // Report progress to 'UI' thread 
          backgroundWorker1.ReportProgress(i); 
          // Simulate long task 
          System.Threading.Thread.Sleep(100); 
        } 
      } 
      // Back on the 'UI' thread so we can update the progress bar 
      void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
      { 
        // The progress percentage is a property of e 
        progressBar1.Value = e.ProgressPercentage; 
      } 
    }