2012-04-09 36 views
0

我正在學習WPF中的backgroundworker類。下面的代碼是在文件MainWindow.xaml.csWPF中的backgroundworker類

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

using System.ComponentModel; 

namespace FrontEnd 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     private BackgroundWorker backGroundWorker; 

     public MainWindow() 
     { 
      InitializeComponent(); 
      backGroundWorker = ((BackgroundWorker)this.FindResource("backgroundWorker")); 
     } 

     private void button1_Click(object sender, RoutedEventArgs e) 
     { 

      button1.IsEnabled = false; 
      Flow pro = new Flow(20,10); 
      backGroundWorker.RunWorkerAsync(pro); 
     } 

     private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      Flow pro = (Flow)e.Argument; 
      e.Result = pro.NaturalNumbers(); 
     } 

     private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      progressBar1.Value= e.ProgressPercentage; 
     } 

     private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if ((int)e.Result == 1) MessageBox.Show("DONE"); 
      progressBar1.Value = 0; 
     } 
    } 
} 

下面的代碼是在文件Flow.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 

namespace FrontEnd 
{ 
    class Flow 
    { 
     long i; 
     //private int x,y; 
     public int X 
     { 
      get; set; 
     } 
     public int Y 
     { 
      get; set; 
     } 

     public Flow(int x, int y) 
     { 
      X = x; 
      Y = y; 
     } 
     public int NaturalNumbers() 
     { 
      for (i = 0; i < 9999; i++) 
      { 
       Console.WriteLine(i); 
       long iteration = i * 100/9999; 
       if ((i % iteration == 0) && 
       (backgroundWorker != null) && backgroundWorker.WorkerReportsProgress) 
       { 
        backgroundWorker.ReportProgress(iteration); 
       } 
      } 
      return 1; 
     } 
    } 
} 

錯誤:「BackgroundWorker的」名稱在當前 不存在背景

如何讓進度條工作?

回答

2

這裏有一個簡單的例子,工作原理:

public partial class BackgroundWorkerPage : Page 
{ 
    private readonly BackgroundWorker _worker = new BackgroundWorker(); 

    public BackgroundWorkerPage() 
    { 
     InitializeComponent(); 

     _worker.DoWork += WorkerOnDoWork; 
     _worker.WorkerReportsProgress = true; 
     _worker.ProgressChanged += WorkerOnProgressChanged; 
    } 

    private void WorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs) 
    { 
     progressBar.Value = progressChangedEventArgs.ProgressPercentage; 
    } 

    private void WorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) 
    { 
     for (int i = 0; i <= 100; i++) 
     { 
      Thread.Sleep(50); 
      _worker.ReportProgress(i); 
     } 
    } 

    private void Button_Click_1(object sender, System.Windows.RoutedEventArgs e) 
    { 
     _worker.RunWorkerAsync(); 
    } 
} 

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <ProgressBar x:Name="progressBar" Height="23" Minimum="0" Maximum="100"/> 
    <Button Grid.Row="1" Height="23" Content="Start" Click="Button_Click_1"/> 
</Grid> 

而且你需要改變你的代碼有點

private void WorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) 
{ 
    var flow = new Flow(_worker); 
    flow.NaturalNumbers(); 
} 

internal class Flow 
{ 
    private readonly BackgroundWorker _worker; 

    public Flow(int x, int y) 
    { 
     X = x; 
     Y = y; 
    } 

    public Flow(BackgroundWorker worker) 
    { 
     _worker = worker; 
    } 

    public int X { get; set; } 
    public int Y { get; set; } 

    public int NaturalNumbers() 
    { 
     for (int i = 0; i <= 9999; i++) 
     { 
      int iteration = i*100/9999; 

      // your if(...) fails with divide by zero exception 

      _worker.ReportProgress(iteration); 
     } 

     return 1; 
    } 
} 
+0

,如果重複了另一類稱爲「** **形象」?的方法內發生的(假設方法是「** ** SendImage」),我要報案進度,剩餘字節數發送。 – SHRI 2012-04-09 09:49:55

+2

執行工作的方法要麼需要對後臺工作者的引用才能調用ReportProgress,要麼可以引發事件或調用委託,以便擁有該工作者的類可以調用ReportProgress。或者您可以直接將進度發送到WPF控件/窗口(使用事件/委託),但您需要使用Dispatcher.Invoke將調用編組到UI線程中。 – Phil 2012-04-09 09:53:32

+0

謝謝分配。 :) – SHRI 2012-04-09 10:11:32

1

介紹

每當我們嘗試做一些長期運行的操作在UI上不凍結它,我們需要在一個單獨的線程中運行它。在本文中,我們將看看BackgroundWorker cl屁股,作爲解決這個問題的一個簡單例子。 BackgroundWorker在單獨的線程上執行操作,並在必要時向UI線程提供通知。 直奔實驗

讓我們創建一個UI作爲下

enter image description here

的目標是,當我們點擊「填充」按鈕,在同一時間,我們應該能夠編寫「文本框」中的某些內容。

現在讓我們看看這是沒有的BackgroundWorker

public partial class WithOutBackgroundThread : Form 
{ 
    List<Employee> lstEmp; 

    public WithOutBackgroundThread() 
    { 
     InitializeComponent(); 
     lstEmp = new List<Employee>(); 
    } 

    private void btnPopulate_Click(object sender, EventArgs e) 
    { 
     GetEmployeeRecords(); 
     dataGridView1.DataSource = lstEmp; 
     lblStatus.Text = "Work Completed"; 
    } 

    //Prepare the data 
    private void GetEmployeeRecords() 
    { 
     for (int i = 1; i <= 10; i++) 
     { 
      // Simulate a pause 
      Thread.Sleep(1000); 
      lstEmp.Add(new Employee { EmpId = i, EmpName = "Name" + i }); 
     } 
    } 
} 

代碼的代碼是非常straightforward.In的「GetEmployeeRecords()」方法,我們正在準備的數據。我們必須引入「主題。睡眠(1000)「來延遲。在「填充」按鈕點擊事件中,我們正在填充網格。

但是,如果我們執行此代碼,用戶界面將變得無法響應,此後,我們無法對「文本框」執行任何任務,這是我們的目標。

從此讓我們改變我們的代碼下面

public partial class WithBackgroundThread : Form 
{ 
    BackgroundWorker workerThread; 
    List<Employee> lstEmp; 

    public WithBackgroundThread() 
    { 
     InitializeComponent(); 

     lstEmp = new List<Employee>(); 
     workerThread = new BackgroundWorker(); 
     workerThread.DoWork += new DoWorkEventHandler(workerThread_DoWork); 
     workerThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted); 

    } 

    private void btnPopulate_Click(object sender, EventArgs e) 
    { 
     workerThread.RunWorkerAsync(); 
    } 

    private void workerThread_DoWork(object sender, DoWorkEventArgs e) 
    { 
     GetEmployeeRecords(); 
    } 

    private void workerThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     lblStatus.Text = "Work Completed"; 
     dataGridView1.DataSource = lstEmp; 
    } 

    //Prepare the data 
    private void GetEmployeeRecords() 
    { 
     for (int i = 1; i <= 10; i++) 
     { 
      // Simulate a pause 
      Thread.Sleep(1000); 
      lstEmp.Add(new Employee { EmpId = i, EmpName = "Name" + i }); 
     } 
    } 
} 

了許多新的東西。我們將探討一個接一個。

首先,我們需要聲明的BackgroundWorker線程

BackgroundWorker workerThread = new BackgroundWorker(); 

接下來,我們需要訂閱事件

workerThread.DoWork += new DoWorkEventHandler(workerThread_DoWork); 
workerThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted); 

作爲第三步,我們需要實現兩個方法

private void workerThread_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // run all background tasks here 
    GetEmployeeRecords(); 
} 

private void workerThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    //update ui once worker complete its work 
    lblStatus.Text = "Work Completed"; 
    dataGridView1.DataSource = lstEmp; 
} 

當我們調用「RunWorkerAsync」方法時會引發「DoWork」事件。這是我們開始執行潛在耗時工作的操作的地方。當後臺操作完成,已被取消或已引發異常時,會觸發「RunWorkerCompleted」事件。

作爲最後一步,調用「填充」按鈕單擊事件中的「RunWorkerAsync」。

private void btnPopulate_Click(object sender, EventArgs e) 
{ 
    workerThread.RunWorkerAsync(); 
} 

「RunWorkerAsync」開始執行後臺操作。

現在,如果我們運行我們的應用程序,我們將能夠填充網格以及在「文本框」上寫入內容。

enter image description here

感謝

相關問題