2011-12-19 43 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的方式做這件事。