与后台工作人员报告LINQ查询的进度,如何?
我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();
}
}
}
}
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);
,无论你要举报
你能解释一下你的第一个代码的继承吗?我真的没有很多有关类的信息:P – 2011-12-19 11:49:09
好的,所以我改变了它,因为当linq查询被执行但输出被创建之前它已经输出。 – 2011-12-19 12:01:52
您还需要报告进度。你可以在getSquare里面,例如发射一个事件。 – 2011-12-19 12:03:43
你可以试试这个:
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的方式做这件事。
每当你找到一场比赛,你都会报告进度;每次发现不匹配时,你想报告进度吗? – Rawling 2011-12-19 11:18:54
我不明白,我在哪里报道了我写的linq查询中匹配的发现?! for循环中的ReportProgress()只是报告数组正在被创建,因为更大的整数需要相当长的时间才能填充数组。对于文本框每次都要报告一行。我没有在实际的linq查询中报告。 – 2011-12-19 11:25:00
Linq是懒惰的;它没有找到每一个匹配,然后将它们传递给你的foreach循环,但是一旦找到每个匹配,就将这些值逐个传递给你的foreach循环。因此,在foreach循环中,您的ReportProgress实质上应该是在每次找到匹配时进行报告。如果没有发生 - 例如你会得到大量的等待,然后是很多快速报告 - 我不知道为什么。 – Rawling 2011-12-19 11:28:54