2014-02-17 50 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; 
      } 
    }