2013-03-07 36 views
1

我試圖在單擊按鈕時顯示進度條,並在工作完成時將其隱藏。但是當我在按鈕事件處理程序中顯示進度條時,它不起作用,並且僅在完成工作後才顯示。在另一個線程中運行進度條

這裏是我的代碼:在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; 
    } 
} 

回答

0

看一看後臺工作(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

0

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

1

發生這種情況是因爲您的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線程上。
相關問題