2012-04-09 34 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

感谢

相关问题