在另一个线程中运行进度条

问题描述:

我试图在单击按钮时显示进度条,并在工作完成时将其隐藏。但是当我在按钮事件处理程序中显示进度条时,它不起作用,并且仅在完成工作后才显示。在另一个线程中运行进度条

这里是我的代码:在WPF

private void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
    this.Dispatcher.BeginInvoke((Action)(() => 
     { 
      loadingprgoress.Visibility = Visibility.Visible; 
     })); 

    int usresult, psresult; 

    con.Open(); 

    SqlDataReader data = null; 
    String myQueryEdit1 = @"SELECT Username, Password FROM [dbo].[Table]"; 
    com.CommandText = myQueryEdit1; 
    com.Connection = con; 
    data = com.ExecuteReader(); 
    Random rnd = new Random(); 
    int newrnd = rnd.Next(1, 100); 

    if (data.Read()) 
    { 

     string userhash = GenerateHashWithSalt(data["Username"].ToString(), newrnd.ToString()); 
     string passhash = GenerateHashWithSalt(data["Password"].ToString(), newrnd.ToString()); 
     string userhash1 = GenerateHashWithSalt("admin", newrnd.ToString()); 
     string passhash1 = GenerateHashWithSalt(pasbox.Password, newrnd.ToString()); 

     usresult = userhash.CompareTo(userhash1); 
     psresult = passhash.ToString().CompareTo(passhash1); 
     if (usresult == 0 && psresult == 0) 
     { 
      con.Close(); 
      dental_main_Window neww = new dental_main_Window(); 
      neww.Show(); 
      Close(); 
     } 
     else 
     { 
      con.Close(); 
      pasbox.Password = ""; 
     } 

     Thread.Sleep(3000); 

     this.Dispatcher.BeginInvoke((Action)(() => 
      { 
       loadingprgoress.Visibility = Visibility.Hidden; 
      })); 
     return; 
    } 
} 

看一看后台工作(http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

它可以让你在一个单独的专用线程上运行操作。 在后台计算,可以提高ProgressChanged的事件,通知UI并相应更新进度:

private BackgroundWorker _worker; 

public Form1(string[] args) 
{ 
    InitializeComponent(); 


    _worker = new BackgroundWorker(); 
    _worker.WorkerReportsProgress = true; 

    _worker.RunWorkerCompleted += worker_WorkCompleted; 
    _worker.DoWork += worker_DoWork; 
    _worker.ProgressChanged += worker_ProgressChanged; 


} 

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    DoStuff(); 
} 
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 
private void worker_WorkCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    _running = false; 
    UpdateUi(); 
} 

private bool DoStuff() 
{ 
     //... 
     _worker.ReportProgress(20); 
     //... 
     _worker.ReportProgress(20); 

     return true; 

} 

private void btnUpdate_Click(object sender, EventArgs e) 
{ 
    _worker.RunWorkerAsync(); 
} 
+0

谢谢你,它工作:) – 2013-03-08 07:11:28

UI需要在UI线程上执行。并且您认识到,因为我可以使用Dispatcher.BeginInvoke与您的进度窗口进行交互。

虽然你的问题是你也在UI线程上执行长时间运行的任务。当你这样做时,你不会让进度窗口有机会运作。线程被长时间运行的任务占用,因此无法为UI提供服务。

解决方案是从UI线程执行长时间运行的任务。

+0

当我这样做,它得到错误,对象是自己对当前线程不能可以通过另一个线程访问。\ – 2013-03-07 09:14:08

+0

然后使用代理从跨线程进行访问。 – James 2013-03-07 09:15:15

+0

然后你需要解决这个问题。它不会改变您需要远离UI线程执行长时间运行的任务的事实。 – 2013-03-07 09:17:28

发生这种情况是因为您的UI线程正在完成所有工作(访问数据库),直到完成,它无法处理更多消息(如显示进度条)。

您需要做相反的事情,在没有BeginInvoke的UI线程中显示进度条,并在另一个线程中执行数据库访问。当其他线程完成时,您需要在UI线程上执行BeginInvoke来隐藏进度条。

这里是另一个重要的注意事项:this.Dispatcher.BeginInvoke不产生线程。它将命令“推入”UI线程的队列,因为所有UI操作必须从UI线程执行。

这里是你做什么:

私人无效Button_Click_1(对象发件人,RoutedEventArgs E)

  1. 显示进度条
  2. 使用任务将启动后台进程
  3. 添加后续任务到您的第一个任务发送消息到UI,该过程已完成
  4. 在继续任务中使用this.Dispatcher.BeginInvoke,以便UI人员发生在UI线程上。