2011-12-19 3 views
1

私は、配列の大きさに等しい、配列内の整数のすべての可能な乗算を出力したアプリケーションexprementingています:大きな数のためにチェックされる必要がある場合はLINQクエリ自体は非常に時間がかかり、特別ですバックグラウンドワーカーによる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を残して、この古い学校のモードを行う必要がありますか?

更新 これは私のコード全体です。進歩裁判は、半分になった後では満たされない。最初の半分は、配列が作成されているとき、2番目の部分は、コードが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

+0

私が書き込んだlinqのクエリで一致の発見を報告したところ、私は理解していませんか? forループの 'ReportProgress()'は、配列が作成されているということにすぎません。なぜなら、より大きなintが配列がいっぱいになるのにかなり時間がかかるからです。また、テキストボックスは、行が追加されるたびにレポートされます。私は実際のlinqクエリの内部に報告がありません。 –

+0

Linqは遅延です。すべての一致を見つけてforeachループに渡すのではなく、それぞれが見つかると直ちに値をforeachループに渡します。したがって、foreachループ内のReportProgressは、一致が見つかるたびにレポートする必要があります。それが起こっていない場合(例:あなたは大規模な待って、多くの迅速なレポートに続いて - 私はなぜわからない。 – Rawling

答えて

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 }; 
そしてメソッドを作成:できた

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

使用法:

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

だけであなたはあなたがこれを試みることができる

+0

最初のコードで継承について説明してください。私は実際にはクラスについて多くの情報を持っていません:P –

+0

大丈夫ですので、linqクエリが実行されたときに出力が作成される前に出力されていたので変更しました。 –

+0

進捗状況も報告する必要があります。たとえばgetSquareの内部でこれを行うことができます。イベントを発生させる。 –

1

を報告したいものは何でもConsole.WriteLine("busy {0}", i);を変更します次のようなもの:

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以外の方法でこれをやる方が良いと思う。

関連する問題