2011-12-19 42 views
1

我exprementing打印出整数的所有可能的乘法在等于数组大小的数组的应用程序:与后台工作人员报告LINQ查询的进度,如何?

private void bgw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    int progress = 0; 

    int toCheck = int.Parse(textBox2.Text); //Number to check for 
    int[] array = new int[toCheck]; 

    //Fill the array 
    for (int i = 0; i < toCheck; i++) 
    { 
     array[i] = i; 
     bgw.ReportProgress(progress); 
     progress += 1; 
    } 

    var result = 
     from i1 in array 
     from i2 in array 
     where i1 * i2 == toCheck 
     let square = i1 * i2 
     select new { i1, i2, square }; //how to report progress here? 

    foreach (var res in result) 
    { 
     textBox1.Text += res.i1 + " * " + res.i2 + " = " + res.square + Environment.NewLine; 

     bgw.ReportProgress(progress); 
     progress += 1; 
    } 
} 

LINQ查询本身是非常耗费时间特别是如果一个大数目应检查。有没有办法报告linq查询的进度?或者我应该离开linq并做这种老派模式?

更新 这是我的整个代码。进度栏在半满后不会填满。前半部分是数组创建时,第二部分是代码尝试执行linq查询时(这就是为什么我认为报告应该在linq查询中完成!)原谅我的愚蠢!

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Diagnostics; 

namespace BGWorkerTest 
{ 
    public partial class Form1 : Form 
    { 
     private PerformanceCounter cpuCounter; 
     private PerformanceCounter ramCounter; 
     string[] diagnosticInfo = new string[2] { string.Empty, string.Empty }; 

     int toCheck = 0; 

     StringBuilder sb; 

     public Form1() 
     { 
      InitializeComponent(); 

      //Diagnostics 
      cpuCounter = new PerformanceCounter(); 

      cpuCounter.CategoryName = "Processor"; 
      cpuCounter.CounterName = "% Processor Time"; 
      cpuCounter.InstanceName = "_Total"; 

      ramCounter = new PerformanceCounter("Memory", "Available KBytes"); 
     } 


     private string[] GetDiagnostics() 
     { 
      diagnosticInfo[0] = string.Format("{0:0.##}", cpuCounter.NextValue()) + "%"; 
      diagnosticInfo[1] = ramCounter.NextValue() + "MB"; 

      return diagnosticInfo; 
     } 

     private void timerStStr_Tick(object sender, EventArgs e) 
     { 
      string[] temp = new string[2] { "", ""}; 
      temp = GetDiagnostics(); 
      ststrLabelCpu.Text = temp[0]; 
      ststrLabelMem.Text = temp[1]; 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      ststrProgBar.Minimum = 0; 
      ststrProgBar.Maximum = 0; 

      toCheck = int.Parse(textBox2.Text); 

      ststrProgBar.Minimum = 0; 
      ststrProgBar.Maximum = toCheck * 2; 
      ststrProgBar.Step = 1; 

      //Starts the backgroundworker process asynchronously 
      bgw.RunWorkerAsync();   
     } 

     private void bgw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      int progress = 0; 

      int[] array = new int[toCheck + 1]; 

      for (int i = 0; i < toCheck + 1; i++) 
      { 
       array[i] = i; 
       bgw.ReportProgress(progress); 
       progress += 1; 
      } 

      var result = 
       from i1 in array 
       from i2 in array 
       where i1 * i2 == toCheck 
       let square = i1 * i2 
       select new { i1, i2, square }; 

      sb = new StringBuilder(); 

      foreach (var res in result) 
      { 
       sb.AppendLine(res.i1 + " * " + res.i2 + " = " + res.square); 

       bgw.ReportProgress(progress); 
       progress += 1; 

       Application.DoEvents(); 
      } 
     } 

     private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      ststrProgBar.PerformStep(); 
     } 

     private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Cancelled) 
      { 
       MessageBox.Show("Operation Cancelled"); 
      } 
      else 
      { 
       MessageBox.Show("Operation Completed"); 

       textBox1.Text = sb.ToString(); 
      } 
     } 
    } 
} 
+0

每当你找到一场比赛,你都会报告进度;每次发现不匹配时,你想报告进度吗? – Rawling 2011-12-19 11:18:54

+0

我不明白,我在哪里报道了我写的linq查询中匹配的发现?! for循环中的ReportProgress()只是报告数组正在被创建,因为更大的整数需要相当长的时间才能填充数组。对于文本框每次都要报告一行。我没有在实际的linq查询中报告。 – 2011-12-19 11:25:00

+0

Linq是懒惰的;它没有找到每一个匹配,然后将它们传递给你的foreach循环,但是一旦找到每个匹配,就将这些值逐个传递给你的foreach循环。因此,在foreach循环中,您的ReportProgress实质上应该是在每次找到匹配时进行报告。如果没有发生 - 例如你会得到大量的等待,然后是很多快速报告 - 我不知道为什么。 – Rawling 2011-12-19 11:28:54

回答

1
var result =  
    from int i1 in array  
    from int i2 in array  
    where i1 * i2 == toCheck  
    let square = getSquare(i1,i2)  
    select new { i1, i2, square }; 

,然后创建方法:

public static int getSquare(int i, int i2) 
    { 
     Console.WriteLine("busy {0}", i); 
     return i * i2; 
    } 

只是改变Console.WriteLine("busy {0}", i);,无论你要举报

+0

你能解释一下你的第一个代码的继承吗?我真的没有很多有关类的信息:P – 2011-12-19 11:49:09

+0

好的,所以我改变了它,因为当linq查询被执行但输出被创建之前它已经输出。 – 2011-12-19 12:01:52

+0

您还需要报告进度。你可以在getSquare里面,例如发射一个事件。 – 2011-12-19 12:03:43

1

你可以试试这个:

private static IEnumerable<T> ActAsEnumerated<T>(this IEnumerable<T> source, Action<T> act) 
{ 
    foreach(var t in source) 
    { 
     act(t); 
     yield return t; 
    } 
} 

使用率的像这样:

var pairs = from i1 in array from i2 in array select new { int1 = i1, int2 = i2 }; 
var reportPairs = pairs.ActAsEnumerated(p => { bgw.ReportProgress(progress); progress += 1; }); 

var result = 
    from pair in reportPairs 
    where pair.int1 * pair.int2 == toCheck 
    let square = pair.int1 * pair.int2 
    select new { pair.int1, pair.int2, square }; 

这真的不是很漂亮。真的,我认为你最好以非Linq的方式做这件事。